

<!DOCTYPE html>
<html lang="zh-CN" data-default-color-scheme=auto>



<head>
  <meta charset="UTF-8">
  <link rel="apple-touch-icon" sizes="76x76" href="/img/fluid.png">
  <link rel="icon" href="/img/fluid.png">
  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0, shrink-to-fit=no">
  <meta http-equiv="x-ua-compatible" content="ie=edge">
  
  <meta name="theme-color" content="#2f4154">
  <meta name="author" content="John Doe">
  <meta name="keywords" content="">
  
    <meta name="description" content="@[toc] 1. 运行环境  Node v16.15.1 VSCode 2022  2. 常用内置API 2.1 fs文件模块读取文件，语法： 1fs.readFile(path, encoding, callback(error, info) 参数说明：  path ，读取文件所在路径 encoding，读取文件的编码 callback，读取文件后执行的回调 error，若出错则为异常，否则为">
<meta property="og:type" content="article">
<meta property="og:title" content="Node 笔记1 _ 常用内置 API _ 模块化编程 _ 自定义 npm包并发布到官方 _ Express 模块的使用 _ Node 解决跨域问题 _ Node 操作 MySQL">
<meta property="og:url" content="http://example.com/2022/08/22/Node%20%E7%AC%94%E8%AE%B01%20_%20%E5%B8%B8%E7%94%A8%E5%86%85%E7%BD%AE%20API%20_%20%E6%A8%A1%E5%9D%97%E5%8C%96%E7%BC%96%E7%A8%8B%20_%20%E8%87%AA%E5%AE%9A%E4%B9%89%20npm%E5%8C%85%E5%B9%B6%E5%8F%91%E5%B8%83%E5%88%B0%E5%AE%98%E6%96%B9%20_%20Express%20%E6%A8%A1%E5%9D%97%E7%9A%84%E4%BD%BF%E7%94%A8%20_%20Node%20%E8%A7%A3%E5%86%B3%E8%B7%A8%E5%9F%9F%E9%97%AE%E9%A2%98%20_%20Node%20%E6%93%8D%E4%BD%9C%20MySQL/index.html">
<meta property="og:site_name" content="Hexo">
<meta property="og:description" content="@[toc] 1. 运行环境  Node v16.15.1 VSCode 2022  2. 常用内置API 2.1 fs文件模块读取文件，语法： 1fs.readFile(path, encoding, callback(error, info) 参数说明：  path ，读取文件所在路径 encoding，读取文件的编码 callback，读取文件后执行的回调 error，若出错则为异常，否则为">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="https://img-blog.csdnimg.cn/4cef8c7f893449629738c230f89ad839.png">
<meta property="og:image" content="https://img-blog.csdnimg.cn/bc34cdc58cbf461fa098a3b53e3b7085.png">
<meta property="og:image" content="https://img-blog.csdnimg.cn/f0acb4b94a5246d986fc7dec22635f12.png">
<meta property="og:image" content="https://img-blog.csdnimg.cn/37ceee55e4824ce8a0ac9d55eb94e65e.png">
<meta property="og:image" content="https://img-blog.csdnimg.cn/4291807d4d6c4d8492bd9ae95c097e60.png">
<meta property="og:image" content="https://img-blog.csdnimg.cn/a9ee8cce4a5e4ac499828afaa48e51ee.png">
<meta property="og:image" content="https://img-blog.csdnimg.cn/4b9b5e56cac340f28ce659fb5a10ad32.png">
<meta property="og:image" content="https://img-blog.csdnimg.cn/b4112dc2af55432d8dd8a62dc1d58db3.png">
<meta property="og:image" content="https://img-blog.csdnimg.cn/1867e9d52eab4b6e85934685c1eb32c1.png">
<meta property="og:image" content="https://img-blog.csdnimg.cn/ba6508230b514612b0d6d601724bc87e.png">
<meta property="og:image" content="https://img-blog.csdnimg.cn/753715266fae497bb469ce73be92efaa.png">
<meta property="og:image" content="https://img-blog.csdnimg.cn/23a203be92754e5f848f364c63378ae8.png">
<meta property="og:image" content="https://img-blog.csdnimg.cn/bdd7069b609d4976b702c57f10c54e26.png">
<meta property="og:image" content="https://img-blog.csdnimg.cn/f14dfea650a54d8595fbf283dcd1a99b.png">
<meta property="og:image" content="https://img-blog.csdnimg.cn/17de54b3c5044995a4c2398dd81b4411.png">
<meta property="og:image" content="https://img-blog.csdnimg.cn/10e8fef5e852444683b473097b8423aa.png">
<meta property="og:image" content="https://img-blog.csdnimg.cn/641c0a464e2048b5a93c9f252d442d51.png">
<meta property="og:image" content="https://img-blog.csdnimg.cn/c3b4af7f93c743748a24ecd3e27fd005.png">
<meta property="og:image" content="https://img-blog.csdnimg.cn/28902a9fcdbd44c0a7ee199c095de124.png">
<meta property="og:image" content="https://img-blog.csdnimg.cn/ed848bd793204e9b9cc024f83ab41fde.png">
<meta property="article:published_time" content="2022-08-22T01:33:26.000Z">
<meta property="article:modified_time" content="2022-08-22T15:47:17.565Z">
<meta property="article:author" content="John Doe">
<meta property="article:tag" content="Node">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:image" content="https://img-blog.csdnimg.cn/4cef8c7f893449629738c230f89ad839.png">
  
  
  
  <title>Node 笔记1 _ 常用内置 API _ 模块化编程 _ 自定义 npm包并发布到官方 _ Express 模块的使用 _ Node 解决跨域问题 _ Node 操作 MySQL - Hexo</title>

  <link  rel="stylesheet" href="https://lib.baomitu.com/twitter-bootstrap/4.6.1/css/bootstrap.min.css" />



  <link  rel="stylesheet" href="https://lib.baomitu.com/github-markdown-css/4.0.0/github-markdown.min.css" />

  <link  rel="stylesheet" href="https://lib.baomitu.com/hint.css/2.7.0/hint.min.css" />

  <link  rel="stylesheet" href="https://lib.baomitu.com/fancybox/3.5.7/jquery.fancybox.min.css" />



<!-- 主题依赖的图标库，不要自行修改 -->
<!-- Do not modify the link that theme dependent icons -->

<link rel="stylesheet" href="//at.alicdn.com/t/font_1749284_hj8rtnfg7um.css">



<link rel="stylesheet" href="//at.alicdn.com/t/font_1736178_lbnruvf0jn.css">


<link  rel="stylesheet" href="/css/main.css" />


  <link id="highlight-css" rel="stylesheet" href="/css/highlight.css" />
  
    <link id="highlight-css-dark" rel="stylesheet" href="/css/highlight-dark.css" />
  




  <script id="fluid-configs">
    var Fluid = window.Fluid || {};
    Fluid.ctx = Object.assign({}, Fluid.ctx)
    var CONFIG = {"hostname":"example.com","root":"/","version":"1.9.2","typing":{"enable":true,"typeSpeed":70,"cursorChar":"_","loop":false,"scope":[]},"anchorjs":{"enable":true,"element":"h1,h2,h3,h4,h5,h6","placement":"left","visible":"hover","icon":""},"progressbar":{"enable":true,"height_px":3,"color":"#29d","options":{"showSpinner":false,"trickleSpeed":100}},"code_language":{"enable":true,"default":"TEXT"},"copy_btn":true,"image_caption":{"enable":true},"image_zoom":{"enable":true,"img_url_replace":["",""]},"toc":{"enable":true,"placement":"right","headingSelector":"h1,h2,h3,h4,h5,h6","collapseDepth":0},"lazyload":{"enable":true,"loading_img":"/img/loading.gif","onlypost":false,"offset_factor":2},"web_analytics":{"enable":false,"follow_dnt":true,"baidu":null,"google":null,"gtag":null,"tencent":{"sid":null,"cid":null},"woyaola":null,"cnzz":null,"leancloud":{"app_id":null,"app_key":null,"server_url":null,"path":"window.location.pathname","ignore_local":false}},"search_path":"/local-search.xml"};

    if (CONFIG.web_analytics.follow_dnt) {
      var dntVal = navigator.doNotTrack || window.doNotTrack || navigator.msDoNotTrack;
      Fluid.ctx.dnt = dntVal && (dntVal.startsWith('1') || dntVal.startsWith('yes') || dntVal.startsWith('on'));
    }
  </script>
  <script  src="/js/utils.js" ></script>
  <script  src="/js/color-schema.js" ></script>
  


  
<meta name="generator" content="Hexo 6.2.0"></head>


<body>
  

  <header>
    

<div class="header-inner" style="height: 70vh;">
  <nav id="navbar" class="navbar fixed-top  navbar-expand-lg navbar-dark scrolling-navbar">
  <div class="container">
    <a class="navbar-brand" href="/">
      <strong>尤 Ni&#39;s Blog</strong>
    </a>

    <button id="navbar-toggler-btn" class="navbar-toggler" type="button" data-toggle="collapse"
            data-target="#navbarSupportedContent"
            aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
      <div class="animated-icon"><span></span><span></span><span></span></div>
    </button>

    <!-- Collapsible content -->
    <div class="collapse navbar-collapse" id="navbarSupportedContent">
      <ul class="navbar-nav ml-auto text-center">
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/">
                <i class="iconfont icon-home-fill"></i>
                首页
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/archives/">
                <i class="iconfont icon-archive-fill"></i>
                归档
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/categories/">
                <i class="iconfont icon-category-fill"></i>
                分类
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/tags/">
                <i class="iconfont icon-tags-fill"></i>
                标签
              </a>
            </li>
          
        
          
          
          
          
            <li class="nav-item">
              <a class="nav-link" href="/about/">
                <i class="iconfont icon-user-fill"></i>
                关于
              </a>
            </li>
          
        
        
          <li class="nav-item" id="search-btn">
            <a class="nav-link" target="_self" href="javascript:;" data-toggle="modal" data-target="#modalSearch" aria-label="Search">
              &nbsp;<i class="iconfont icon-search"></i>&nbsp;
            </a>
          </li>
          
        
        
          <li class="nav-item" id="color-toggle-btn">
            <a class="nav-link" target="_self" href="javascript:;" aria-label="Color Toggle">&nbsp;<i
                class="iconfont icon-dark" id="color-toggle-icon"></i>&nbsp;</a>
          </li>
        
      </ul>
    </div>
  </div>
</nav>

  

<div id="banner" class="banner" parallax=true
     style="background: url('/img/default.png') no-repeat center center; background-size: cover;">
  <div class="full-bg-img">
    <div class="mask flex-center" style="background-color: rgba(0, 0, 0, 0.3)">
      <div class="banner-text text-center fade-in-up">
        <div class="h2">
          
            <span id="subtitle" data-typed-text="Node 笔记1 _ 常用内置 API _ 模块化编程 _ 自定义 npm包并发布到官方 _ Express 模块的使用 _ Node 解决跨域问题 _ Node 操作 MySQL"></span>
          
        </div>

        
          
  <div class="mt-3">
    
      <span class="post-meta mr-2">
        <i class="iconfont icon-author" aria-hidden="true"></i>
        John Doe
      </span>
    
    
      <span class="post-meta">
        <i class="iconfont icon-date-fill" aria-hidden="true"></i>
        <time datetime="2022-08-22 09:33" pubdate>
          2022年8月22日 上午
        </time>
      </span>
    
  </div>

  <div class="mt-1">
    
      <span class="post-meta mr-2">
        <i class="iconfont icon-chart"></i>
        
          29k 字
        
      </span>
    

    
      <span class="post-meta mr-2">
        <i class="iconfont icon-clock-fill"></i>
        
        
        
          245 分钟
        
      </span>
    

    
    
  </div>


        
      </div>

      
    </div>
  </div>
</div>

</div>

  </header>

  <main>
    
      

<div class="container-fluid nopadding-x">
  <div class="row nomargin-x">
    <div class="side-col d-none d-lg-block col-lg-2">
      

    </div>

    <div class="col-lg-8 nopadding-x-md">
      <div class="container nopadding-x-md" id="board-ctn">
        <div id="board">
          <article class="post-content mx-auto">
            <!-- SEO header -->
            <h1 style="display: none">Node 笔记1 _ 常用内置 API _ 模块化编程 _ 自定义 npm包并发布到官方 _ Express 模块的使用 _ Node 解决跨域问题 _ Node 操作 MySQL</h1>
            
              <p class="note note-info">
                
                  
                    本文最后更新于：1 小时前
                  
                
              </p>
            
            
              <div class="markdown-body">
                
                <p>@[toc]</p>
<h1 id="1-运行环境"><a href="#1-运行环境" class="headerlink" title="1. 运行环境"></a>1. 运行环境</h1><hr>
<ul>
<li>Node v16.15.1</li>
<li>VSCode 2022</li>
</ul>
<h1 id="2-常用内置API"><a href="#2-常用内置API" class="headerlink" title="2. 常用内置API"></a>2. 常用内置API</h1><hr>
<h2 id="2-1-fs文件模块"><a href="#2-1-fs文件模块" class="headerlink" title="2.1 fs文件模块"></a>2.1 fs文件模块</h2><p>读取文件，语法：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs javascript">fs.<span class="hljs-title function_">readFile</span>(path, encoding, <span class="hljs-title function_">callback</span>(error, info)<br></code></pre></td></tr></table></figure>
<p>参数说明：</p>
<ul>
<li>path ，读取文件所在路径</li>
<li>encoding，读取文件的编码</li>
<li>callback，读取文件后执行的回调<ul>
<li>error，若出错则为异常，否则为 null</li>
<li>info 为读取的结果，若读取错误则为 undefined</li>
</ul>
</li>
</ul>
<p>【例1】读取文件</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><code class="hljs javascript"><span class="hljs-keyword">const</span> fs = <span class="hljs-built_in">require</span>(<span class="hljs-string">&#x27;fs&#x27;</span>)<br><br>fs.<span class="hljs-title function_">readFile</span>(<span class="hljs-string">&#x27;./demo.txt&#x27;</span>, <span class="hljs-string">&#x27;utf8&#x27;</span>, <span class="hljs-keyword">function</span>(<span class="hljs-params">err, result</span>)&#123;<br>    <span class="hljs-keyword">if</span>(err == <span class="hljs-literal">null</span>)<br>        <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">&#x27;读取成功, result=&#x27;</span>, result)<br>    <span class="hljs-keyword">else</span> &#123;<br>        <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">&#x27;读取失败, result=&#x27;</span>, result)<br>    &#125;<br>&#125;)<br></code></pre></td></tr></table></figure>

<p>写入文件语法：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs javascript">fs.<span class="hljs-title function_">writeFile</span>(file, data[, options], callback)<br></code></pre></td></tr></table></figure>
<p>参数说明：</p>
<ul>
<li>file，必选，指定文件保存的路径</li>
<li>data，必选，表示要写入的内容<ul>
<li>options，可选参数，表示以什么格式写入内容，默认为 utf8</li>
</ul>
</li>
<li>callback 必选，回调函数，文件写入后执行的回调函数</li>
</ul>
<p>【例2】写入文件</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><code class="hljs javascript"><span class="hljs-keyword">const</span> fs = <span class="hljs-built_in">require</span>(<span class="hljs-string">&#x27;fs&#x27;</span>)<br><span class="hljs-comment">// 定义要写入的内容</span><br><span class="hljs-keyword">const</span> user = &#123;<br>  <span class="hljs-attr">name</span>: <span class="hljs-string">&#x27;uni&#x27;</span>,<br>  <span class="hljs-attr">age</span>: <span class="hljs-string">&#x27;22&#x27;</span><br>&#125;<br>fs.<span class="hljs-title function_">writeFile</span>(<span class="hljs-string">&#x27;./demo2.txt&#x27;</span>, <span class="hljs-title class_">JSON</span>.<span class="hljs-title function_">stringify</span>(user), <span class="hljs-keyword">function</span>(<span class="hljs-params">err</span>)&#123;<br>    <span class="hljs-keyword">if</span>(err == <span class="hljs-literal">null</span>)<br>        <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">&#x27;保存成功&#x27;</span>)<br>    <span class="hljs-keyword">else</span> &#123;<br>        <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">&#x27;保存失败&#x27;</span>)<br>    &#125;<br>&#125;)<br></code></pre></td></tr></table></figure>
<p>注：Node.js 支持 __dirname 获取当前 js 脚本的运行目录</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs javascript"><span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">&#x27;目录:&#x27;</span>, __dirname) <br></code></pre></td></tr></table></figure>

<h2 id="2-2-path-路径模块"><a href="#2-2-path-路径模块" class="headerlink" title="2.2 path 路径模块"></a>2.2 path 路径模块</h2><p>path 模块是 Node.js 官方提供的、用来处理路径的模块。</p>
<h3 id="2-2-1-path-join-拼接字符串"><a href="#2-2-1-path-join-拼接字符串" class="headerlink" title="2.2.1 path.join 拼接字符串"></a>2.2.1 path.join 拼接字符串</h3><p>path.join() 方法可以把多个路径片段拼接为完整的路径字符串</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs javascript"><span class="hljs-keyword">const</span> path = <span class="hljs-built_in">require</span>(<span class="hljs-string">&#x27;path&#x27;</span>)<br><br><span class="hljs-keyword">const</span> pathstr = path.<span class="hljs-title function_">join</span>(<span class="hljs-string">&#x27;/a&#x27;</span>, <span class="hljs-string">&#x27;/b/c&#x27;</span>, <span class="hljs-string">&#x27;../&#x27;</span>, <span class="hljs-string">&#x27;./d&#x27;</span>, <span class="hljs-string">&#x27;e&#x27;</span>)<br><span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(pathstr)	<span class="hljs-comment">// 拼接结果: \a\b\d\e</span><br></code></pre></td></tr></table></figure>
<p>注：Node.js 中路径拼接的操作通常都是使用 path.join() 而不是使用加号直接拼接</p>
<h3 id="2-2-2-path-basename-获取文件名"><a href="#2-2-2-path-basename-获取文件名" class="headerlink" title="2.2.2 path.basename() 获取文件名"></a>2.2.2 path.basename() 获取文件名</h3><p>path.basename() 方法可以获取路径中的最后一部分，这个方法经常用来获取路径中的文件名</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs javascript"><span class="hljs-keyword">const</span> path = <span class="hljs-built_in">require</span>(<span class="hljs-string">&#x27;path&#x27;</span>)<br><br><span class="hljs-keyword">const</span> filePath = path.<span class="hljs-title function_">join</span>(__dirname, <span class="hljs-string">&#x27;demo.txt&#x27;</span>)<br><span class="hljs-keyword">const</span> fileName = path.<span class="hljs-title function_">basename</span>(filePath)<br><br><span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">&#x27;文件路径: &#x27;</span>, filePath)<br><span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">&#x27;文件名: &#x27;</span>, fileName)<br></code></pre></td></tr></table></figure>
<blockquote>
<p>运行结果<br>文件路径:  H:\javascript-demo\demo.txt<br>文件名:  demo.txt</p>
</blockquote>
<h3 id="2-2-3-path-extname-获取扩展名"><a href="#2-2-3-path-extname-获取扩展名" class="headerlink" title="2.2.3 path.extname() 获取扩展名"></a>2.2.3 path.extname() 获取扩展名</h3><p>path.extname()可获取路径中的文件拓展名，通常用来获取文件的类型</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs javascript"><span class="hljs-keyword">const</span> path = <span class="hljs-built_in">require</span>(<span class="hljs-string">&#x27;path&#x27;</span>)<br><br><span class="hljs-keyword">const</span> filePath = path.<span class="hljs-title function_">join</span>(__dirname, <span class="hljs-string">&#x27;demo.txt&#x27;</span>)<br><span class="hljs-keyword">const</span> fileType = path.<span class="hljs-title function_">extname</span>(filePath)<br><br><span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">&#x27;文件路径: &#x27;</span>, filePath)<br><span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">&#x27;文件类型: &#x27;</span>, fileType)<br></code></pre></td></tr></table></figure>
<blockquote>
<p>运行结果<br>文件路径:  H:\javascript-demo\demo.txt<br>文件类型:  .txt</p>
</blockquote>
<h2 id="2-3-http-模块"><a href="#2-3-http-模块" class="headerlink" title="2.3 http 模块"></a>2.3 http 模块</h2><p>http 模块是 Node.js 官方提供的、用来创建 web 服务器的模块</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><code class="hljs javascript"><span class="hljs-keyword">const</span> http = <span class="hljs-built_in">require</span>(<span class="hljs-string">&#x27;http&#x27;</span>)<br><br><span class="hljs-keyword">const</span> server = http.<span class="hljs-title function_">createServer</span>()<br><br>server.<span class="hljs-title function_">on</span>(<span class="hljs-string">&#x27;request&#x27;</span>, <span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> &#123;<br>    res.<span class="hljs-title function_">end</span>(<span class="hljs-string">&#x27;服务器已启动成功&#x27;</span>)<br>&#125;)<br><br>server.<span class="hljs-title function_">listen</span>(<span class="hljs-number">8080</span>, <span class="hljs-function">() =&gt;</span> &#123;<br>    <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">&#x27;server running at http://127.0.0.1:8080&#x27;</span>)<br>&#125;)<br></code></pre></td></tr></table></figure>

<p>【例】使用 Node.js 的 http模块 实现不同 URL 访问返回不同的 HTML 内容</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><code class="hljs javascript"><span class="hljs-keyword">const</span> http = <span class="hljs-built_in">require</span>(<span class="hljs-string">&#x27;http&#x27;</span>)<br><br><span class="hljs-keyword">const</span> server = http.<span class="hljs-title function_">createServer</span>()<br><br>server.<span class="hljs-title function_">on</span>(<span class="hljs-string">&#x27;request&#x27;</span>, <span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> &#123;<br>    <span class="hljs-comment">// 获取请求的url地址</span><br>    <span class="hljs-keyword">const</span> url = req.<span class="hljs-property">url</span><br>    <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">&#x27;请求地址:&#x27;</span>, req.<span class="hljs-property">url</span>)<br>    <span class="hljs-comment">// 定义返回的 HTML 内容</span><br>    <span class="hljs-keyword">let</span> content = <span class="hljs-string">&#x27;&lt;h1&gt;404 Not found!&lt;/h1&gt;&#x27;</span><br>    <span class="hljs-comment">// 根据请求的 URL 返回不同的 HTML 内容</span><br>    <span class="hljs-keyword">if</span>(url === <span class="hljs-string">&#x27;/&#x27;</span> || url === <span class="hljs-string">&#x27;/index.html&#x27;</span>)&#123;<br>        content = <span class="hljs-string">&#x27;&lt;h1&gt;首页&lt;/h1&gt;&#x27;</span><br>    &#125; <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span>(url === <span class="hljs-string">&#x27;/about.html&#x27;</span>)&#123;<br>        content = <span class="hljs-string">&#x27;&lt;h1&gt;关于页面&lt;/h1&gt;&#x27;</span><br>    &#125;<br>    <span class="hljs-comment">// 设置响应头, 解决中文乱码问题</span><br>    res.<span class="hljs-title function_">setHeader</span>(<span class="hljs-string">&#x27;Content-Type&#x27;</span>, <span class="hljs-string">&#x27;text/html;charset=utf-8&#x27;</span>)<br>    <span class="hljs-comment">// 调用 end 方法，返回内容给客户端</span><br>    res.<span class="hljs-title function_">end</span>(content)<br>&#125;)<br><br>server.<span class="hljs-title function_">listen</span>(<span class="hljs-number">8080</span>, <span class="hljs-function">() =&gt;</span> &#123;<br>    <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">&#x27;server running at http://127.0.0.1:8080&#x27;</span>)<br>&#125;)<br></code></pre></td></tr></table></figure>

<h1 id="3-模块化编程"><a href="#3-模块化编程" class="headerlink" title="3. 模块化编程"></a>3. 模块化编程</h1><hr>
<p>Node.js 根据模块来源不同，将模块分为三大类，分别是：</p>
<ul>
<li>内置模块，例如 fs、path、http 等</li>
<li>自定义模块，用户创建的每个 .js 文件都属于自定义模块</li>
<li>第三方模块（由第三方开发出来的模块，使用前需使用 node install 命令下载）</li>
</ul>
<p>Node.js 提供 require()方法来加载上述的模块，加载时可忽略 .js 文件后缀</p>
<p><strong>模块作用域</strong><br>和函数作用域类似，在自定义模块中定义的变量、方法等成员，只能在当前模块内被访问，这种模块级别的访问限制，叫做模块作用域</p>
<p><strong>module 对象</strong><br>node.js 提供了 module 内置对象，我们可以直接访问，其内部存储了和当前js模块有关的信息</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs javascript"><span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-variable language_">module</span>)<br></code></pre></td></tr></table></figure>
<blockquote>
<p>运行结果<br>Module {<br>  id: ‘.’,<br>  path: ‘H:\javascript-demo’,<br>  exports: {},<br>  filename: ‘H:\javascript-demo\index.js’,<br>  loaded: false,<br>  children: [],<br>  paths: [ ‘H:\javascript-demo\node_modules’, ‘H:\node_modules’ ]<br>}</p>
</blockquote>
<p>其中的 <strong>exports</strong> 表示模块暴露的内容，当其他 node.js 文件引入该模块时，加载的就是 exports 指向的对象</p>
<p>【例】自定义一个 user 模块，然后在另一个 js 文件里引入它并执行<br><code>user.js</code></p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><code class="hljs javascript"><span class="hljs-variable language_">module</span>.<span class="hljs-property">exports</span>=&#123;<br>    <span class="hljs-attr">name</span>: <span class="hljs-string">&#x27;user.js&#x27;</span>,<br>    <span class="hljs-attr">user</span>: &#123;<br>        <span class="hljs-attr">name</span>: <span class="hljs-string">&#x27;uni&#x27;</span>,<br>        <span class="hljs-attr">age</span>: <span class="hljs-number">22</span><br>    &#125;,<br>    <span class="hljs-title function_">getUser</span>(<span class="hljs-params"></span>)&#123;<br>        <span class="hljs-keyword">return</span> <span class="hljs-title class_">JSON</span>.<span class="hljs-title function_">stringify</span>(<span class="hljs-variable language_">this</span>.<span class="hljs-property">user</span>)<br>    &#125;<br>&#125;<br></code></pre></td></tr></table></figure>
<p><code>index.js</code></p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs javascript"><span class="hljs-keyword">const</span> user = <span class="hljs-built_in">require</span>(<span class="hljs-string">&#x27;./user&#x27;</span>)<br><br><span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(user.<span class="hljs-title function_">getUser</span>())<br></code></pre></td></tr></table></figure>
<blockquote>
<p>运行结果<br>{“name”:”uni”,”age”:22}</p>
</blockquote>
<h1 id="4-npm-包"><a href="#4-npm-包" class="headerlink" title="4. npm 包"></a>4. npm 包</h1><hr>
<p>Node.js 中的第三方模块又叫做包。</p>
<p>全球最大的包共享平台 <a target="_blank" rel="noopener" href="https://www.npmjs.com/">https://www.npmjs.com/</a>，这上面有上百万的开源包可以使用。</p>
<p>Node.js 使用的包管理工具为 Node Package Manager，在安装 node.js 后，系统变量会设置好支持 npm 命令的环境，之后就可以在终端使用 npm 命令</p>
<p><img src="https://img-blog.csdnimg.cn/4cef8c7f893449629738c230f89ad839.png" srcset="/img/loading.gif" lazyload alt="在这里插入图片描述"></p>
<p>【例】通过 npm 安装 moment 时间处理的包，输出格式化的时间</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs shell">npm install moment<br></code></pre></td></tr></table></figure>

<p>如果是在一个文件夹里运行这个命令，那么就会产生以下这三个文件<br><img src="https://img-blog.csdnimg.cn/bc34cdc58cbf461fa098a3b53e3b7085.png" srcset="/img/loading.gif" lazyload alt="在这里插入图片描述"></p>
<ul>
<li>node_modules ，存放所有已安装到项目中的包，require() 导入第三方包时就是从这个目录中查找并加载包</li>
<li>package-lock.json，记录 node_modules 目录下每一个包的下载信息，例如包的名字、版本号和下载地址等</li>
<li>package.json，记录与项目有关的配置信息<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs javascript"><span class="hljs-keyword">const</span> moment = <span class="hljs-built_in">require</span>(<span class="hljs-string">&#x27;moment&#x27;</span>)<br><br><span class="hljs-keyword">const</span> dt = <span class="hljs-title function_">moment</span>().<span class="hljs-title function_">format</span>(<span class="hljs-string">&#x27;YYYY-MM-DD HH:mm:ss&#x27;</span>)<br><br><span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(dt)	<span class="hljs-comment">// 2022-08-17 14:54:29</span><br></code></pre></td></tr></table></figure>
在使用 npm install 命令时候，在包名添加@版本号 可安装指定的版本，例如：<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs shell">npm install moment@2.22.2<br></code></pre></td></tr></table></figure>
在安装后 package.json 里的内容为：<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs json"><span class="hljs-punctuation">&#123;</span><br>  <span class="hljs-attr">&quot;dependencies&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">&#123;</span><br>    <span class="hljs-attr">&quot;moment&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-string">&quot;^2.22.2&quot;</span><br>  <span class="hljs-punctuation">&#125;</span><br><span class="hljs-punctuation">&#125;</span><br></code></pre></td></tr></table></figure>
<strong>版本号规范</strong></li>
</ul>
<p>Node 包的版本号是以点分隔的，共有三个数字，比如：1.1.10<br>分别表示：</p>
<ul>
<li>第1位数字，大版本号</li>
<li>第2位数字，功能版本</li>
<li>第3位数字，Bug修复版本</li>
</ul>
<p>版本号升级的规则：只要前面的版本号升级，那么后面的版本号都归零</p>
<p>注：nodule_module 比较占空间，而在共享项目时不用附带，因为只要有 package.json 配置文件，一执行 npm install 命令就会下载文件里指定的所有依赖。</p>
<p>npm 提供了快捷命令 npm init -y 初始化，-y表示直接同意命令中的提示，这个命令有个问题，就是不支持中文的路径，所以node项目最好不要包含中文名路径</p>
<h2 id="4-1-切换-npm-镜像"><a href="#4-1-切换-npm-镜像" class="headerlink" title="4.1 切换 npm 镜像"></a>4.1 切换 npm 镜像</h2><p>npm 默认下载地址为国外的：<a target="_blank" rel="noopener" href="https://registry.npmjs.org/%EF%BC%8C%E4%B8%8B%E8%BD%BD%E9%80%9F%E5%BA%A6%E6%B2%A1%E6%9C%89%E5%9B%BD%E5%86%85%E7%9A%84%E9%95%9C%E5%83%8F%E7%AB%99%E5%BF%AB">https://registry.npmjs.org/，下载速度没有国内的镜像站快</a></p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs javascript"><span class="hljs-comment">// 查看当前的下包镜像源</span><br>npm config get registry<br><br><span class="hljs-comment">// 将下包的镜像切换为淘宝镜像源</span><br>npm config set registry=<span class="hljs-attr">https</span>:<span class="hljs-comment">//registry.npm.taobao.org/</span><br><br><span class="hljs-comment">// 检查镜像源是否下载成功</span><br>npm config get registry<br></code></pre></td></tr></table></figure>

<p><img src="https://img-blog.csdnimg.cn/f0acb4b94a5246d986fc7dec22635f12.png" srcset="/img/loading.gif" lazyload alt="在这里插入图片描述"></p>
<p>除了上述这种手动替换 npm 镜像的方式以外，可以安装一个 nrm 小工具来实现镜像的切换</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs shell"><span class="hljs-meta prompt_"># </span><span class="language-bash">将 nrm 安装为全局可用的工具</span><br>npm i nrm -g<br><span class="hljs-meta prompt_"># </span><span class="language-bash">查看所有可用的镜像源</span><br>nrm ls<br><span class="hljs-meta prompt_"># </span><span class="language-bash">将下载包的镜像源切换为 taobao 镜像</span><br>nrm use taobao<br></code></pre></td></tr></table></figure>

<h2 id="4-2-包的分类"><a href="#4-2-包的分类" class="headerlink" title="4.2 包的分类"></a>4.2 包的分类</h2><p>npm 中的包主要有项目包 和 全局包这两种，被安装到项目的 node_modules 目录中的包都是项目包。</p>
<h3 id="4-2-1-项目包"><a href="#4-2-1-项目包" class="headerlink" title="4.2.1 项目包"></a>4.2.1 项目包</h3><p>项目包分为两大类，分别是：</p>
<ul>
<li>开发依赖包（ package.json 中 devDependencies 节点记录的包）</li>
<li>核心依赖包（ package.json 中 dependencies 节点记录的包）<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs shell">npm i 包名 -D		// 开发依赖包, 会被记录到 devDependencies <br>npm i 包名			// 核心依赖包, 会被记录到 dependencies<br></code></pre></td></tr></table></figure></li>
</ul>
<h3 id="4-2-2-全局包"><a href="#4-2-2-全局包" class="headerlink" title="4.2.2 全局包"></a>4.2.2 全局包</h3><p>在执行 npm install 命令时，若添加 -g 参数，那么安装的包则可以在全局使用<br>安装包的目录在：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs shell">C:\Users\用户目录\AppData\Roaming\npm\node_modules<br></code></pre></td></tr></table></figure>
<p>注：只有工具性质的包，才有全局安装的必要性</p>
<h2 id="4-3-包的规范"><a href="#4-3-包的规范" class="headerlink" title="4.3 包的规范"></a>4.3 包的规范</h2><p>包一般符合以下三点规范：</p>
<ol>
<li>包必须以单独的目录存在</li>
<li>包的顶级目录下必须包含 package.json 这个包管理配置文件</li>
<li>package.jon 必须包含 name、version 和 main 这三个属性，分别代表包的名字、版本号和包的入口</li>
</ol>
<h2 id="4-4-案例-开发自定义的包并发布"><a href="#4-4-案例-开发自定义的包并发布" class="headerlink" title="4.4 案例-开发自定义的包并发布"></a>4.4 案例-开发自定义的包并发布</h2><h3 id="4-4-1-开发包"><a href="#4-4-1-开发包" class="headerlink" title="4.4.1 开发包"></a>4.4.1 开发包</h3><p>自定义一个包，实现时间处理以及 HTML代码解码和编码的功能</p>
<p>项目结构</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><code class="hljs shell">|- uni-tools<br>  |- src<br>    |- dateFormat.js	时间处理脚本<br>    |- htmlEscape.js	HTML内容特殊字符处理脚本<br>  |- package.json	包管理配置文件<br>  |- index.js			包的入口文件<br>  |- README.md			包的说明文档<br>  <br>|- demo.js	 该脚本用于测试 uni-tools 的功能, 不属于包的一部分<br></code></pre></td></tr></table></figure>

<ol>
<li><p><strong>配置包的信息，package.json</strong></p>
<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs json"><span class="hljs-punctuation">&#123;</span><br>    <span class="hljs-attr">&quot;name&quot;</span> <span class="hljs-punctuation">:</span> <span class="hljs-string">&quot;unirithe-demo&quot;</span><span class="hljs-punctuation">,</span><br>    <span class="hljs-attr">&quot;version&quot;</span> <span class="hljs-punctuation">:</span> <span class="hljs-string">&quot;1.0.0&quot;</span><span class="hljs-punctuation">,</span><br>    <span class="hljs-attr">&quot;main&quot;</span> <span class="hljs-punctuation">:</span> <span class="hljs-string">&quot;index.js&quot;</span><span class="hljs-punctuation">,</span><br>    <span class="hljs-attr">&quot;description&quot;</span> <span class="hljs-punctuation">:</span> <span class="hljs-string">&quot;提供了格式化时间, HTMLEscape的功能&quot;</span><span class="hljs-punctuation">,</span><br>    <span class="hljs-attr">&quot;keywords&quot;</span> <span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span><span class="hljs-string">&quot;uni&quot;</span><span class="hljs-punctuation">,</span> <span class="hljs-string">&quot;dateFormat&quot;</span><span class="hljs-punctuation">,</span> <span class="hljs-string">&quot;escape&quot;</span><span class="hljs-punctuation">]</span><span class="hljs-punctuation">,</span><br>    <span class="hljs-attr">&quot;license&quot;</span> <span class="hljs-punctuation">:</span> <span class="hljs-string">&quot;ISC&quot;</span><br><span class="hljs-punctuation">&#125;</span><br></code></pre></td></tr></table></figure>
</li>
<li><p><strong>分别开发时间处理和 HTML 内容解析模块</strong></p>
</li>
</ol>
<p><strong>dateFormat.js</strong></p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><code class="hljs javascript"><span class="hljs-comment">// 定义格式化时间的函数</span><br><span class="hljs-keyword">function</span> <span class="hljs-title function_">dateFormat</span>(<span class="hljs-params">dateStr</span>)&#123;<br>    <span class="hljs-keyword">const</span> dt = <span class="hljs-keyword">new</span> <span class="hljs-title class_">Date</span>(dateStr)<br><br>    <span class="hljs-keyword">const</span> y = <span class="hljs-title function_">padZero</span>(dt.<span class="hljs-title function_">getFullYear</span>())<br><br>    <span class="hljs-keyword">const</span> m = <span class="hljs-title function_">padZero</span>(dt.<span class="hljs-title function_">getMonth</span>() + <span class="hljs-number">1</span>)<br>    <br>    <span class="hljs-keyword">const</span> d = <span class="hljs-title function_">padZero</span>(dt.<span class="hljs-title function_">getDay</span>() )<br><br>    <span class="hljs-keyword">const</span> hh = <span class="hljs-title function_">padZero</span>(dt.<span class="hljs-title function_">getHours</span>())<br><br>    <span class="hljs-keyword">const</span> mm = <span class="hljs-title function_">padZero</span>(dt.<span class="hljs-title function_">getMinutes</span>())<br><br>    <span class="hljs-keyword">const</span> ss = <span class="hljs-title function_">padZero</span>(dt.<span class="hljs-title function_">getSeconds</span>())<br><br>    <span class="hljs-keyword">return</span> <span class="hljs-string">`<span class="hljs-subst">$&#123;y&#125;</span>-<span class="hljs-subst">$&#123;m&#125;</span>-<span class="hljs-subst">$&#123;d&#125;</span> <span class="hljs-subst">$&#123;hh&#125;</span>:<span class="hljs-subst">$&#123;mm&#125;</span>:<span class="hljs-subst">$&#123;ss&#125;</span>`</span><br><br>&#125;<br><br><span class="hljs-comment">// 定义一个补零的函数</span><br><span class="hljs-keyword">function</span> <span class="hljs-title function_">padZero</span>(<span class="hljs-params">n</span>)&#123;<br>    <span class="hljs-keyword">return</span> n &gt; <span class="hljs-number">9</span> ? n : <span class="hljs-string">&#x27;0&#x27;</span> + n<br>&#125;<br><br><span class="hljs-variable language_">module</span>.<span class="hljs-property">exports</span> = &#123;<br>    dateFormat<br>&#125;<br></code></pre></td></tr></table></figure>
<p><strong>htmlEscape.js</strong></p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><code class="hljs javascript"><span class="hljs-comment">// 定义转义 HTML 字符的函数</span><br><span class="hljs-keyword">function</span> <span class="hljs-title function_">htmlEscape</span>(<span class="hljs-params">htmlStr</span>)&#123;<br>    <span class="hljs-keyword">return</span> htmlStr.<span class="hljs-title function_">replace</span>(<span class="hljs-regexp">/&lt;|&gt;|&quot;|&amp;/g</span>, <span class="hljs-function">(<span class="hljs-params">match</span>) =&gt;</span> &#123;<br>        <span class="hljs-keyword">switch</span> (match)&#123;<br>            <span class="hljs-keyword">case</span> <span class="hljs-string">&#x27;&lt;&#x27;</span>:<br>                <span class="hljs-keyword">return</span> <span class="hljs-string">&#x27;&amp;lt;&#x27;</span><br>            <span class="hljs-keyword">case</span> <span class="hljs-string">&#x27;&gt;&#x27;</span>:<br>                <span class="hljs-keyword">return</span> <span class="hljs-string">&#x27;&amp;gt;&#x27;</span><br>            <span class="hljs-keyword">case</span> <span class="hljs-string">&#x27;&quot;&#x27;</span>:<br>                <span class="hljs-keyword">return</span> <span class="hljs-string">&#x27;&amp;quot;&#x27;</span><br>            <span class="hljs-keyword">case</span> <span class="hljs-string">&#x27;&amp;&#x27;</span>:<br>                <span class="hljs-keyword">return</span> <span class="hljs-string">&#x27;&amp;amp;&#x27;</span><br>        &#125;<br>    &#125;)<br>&#125;<br><span class="hljs-comment">// 定义还原 HTML 字符串的函数</span><br><span class="hljs-keyword">function</span> <span class="hljs-title function_">htmlUnEscape</span>(<span class="hljs-params">str</span>)&#123;<br>    <span class="hljs-keyword">return</span> str.<span class="hljs-title function_">replace</span>(<span class="hljs-regexp">/&amp;lt;|&amp;gt;|&amp;quot;|&amp;amp;/g</span>, <span class="hljs-function">(<span class="hljs-params">match</span>) =&gt;</span> &#123;<br>        <span class="hljs-keyword">switch</span>(match) &#123;<br>            <span class="hljs-keyword">case</span> <span class="hljs-string">&#x27;&amp;lt;&#x27;</span>:<br>                <span class="hljs-keyword">return</span> <span class="hljs-string">&#x27;&lt;&#x27;</span><br>            <span class="hljs-keyword">case</span> <span class="hljs-string">&#x27;&amp;gt;&#x27;</span>:<br>                <span class="hljs-keyword">return</span> <span class="hljs-string">&#x27;&gt;&#x27;</span><br>            <span class="hljs-keyword">case</span> <span class="hljs-string">&#x27;&amp;quot;&#x27;</span>:<br>                <span class="hljs-keyword">return</span> <span class="hljs-string">&#x27;&quot;&#x27;</span><br>            <span class="hljs-keyword">case</span> <span class="hljs-string">&#x27;&amp;amp;&#x27;</span>:<br>                <span class="hljs-keyword">return</span> <span class="hljs-string">&#x27;&amp;&#x27;</span><br>        &#125;<br>    &#125;)<br>&#125;<br><br><span class="hljs-variable language_">module</span>.<span class="hljs-property">exports</span> = &#123;<br>    htmlEscape,<br>    htmlUnEscape<br>&#125;<br></code></pre></td></tr></table></figure>

<ol start="3">
<li><p><strong>index.js 包的主要执行脚本</strong></p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><code class="hljs javascript"><span class="hljs-comment">// 包的入口文件</span><br><br><span class="hljs-keyword">const</span> date = <span class="hljs-built_in">require</span>(<span class="hljs-string">&#x27;./src/dateFormat&#x27;</span>)<br><span class="hljs-keyword">const</span> <span class="hljs-built_in">escape</span> = <span class="hljs-built_in">require</span>(<span class="hljs-string">&#x27;./src/htmlEscape&#x27;</span>)<br><br><span class="hljs-comment">// 向外暴露需要的属性</span><br><span class="hljs-variable language_">module</span>.<span class="hljs-property">exports</span> = &#123;<br>    ...date,<br>    ...<span class="hljs-built_in">escape</span><br>&#125;<br></code></pre></td></tr></table></figure>
</li>
<li><p><strong>说明文档 README.md</strong></p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br></pre></td><td class="code"><pre><code class="hljs xml">## 安装<br><br><br>npm install uni-tools<br><br><br>## 导入<br><br><br>const tools = require(&#x27;uni-tools&#x27;)<br><br>## 格式化时间<br><br><br>// 调用 dateFormat 对时间进行格式化, 返回字符串<br>const date = tools.dateFormat(new Date())<br>console.log(date)<br><br><br>运行结果<br>2022-08-04 08:56:43<br><br>## 转义 HTMl 中的特殊字符<br><br><br>// 待转换的 HTML 字符串<br>const htmlStr1 = &#x27;<span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">title</span>=<span class="hljs-string">&quot;xxx&quot;</span>&gt;</span>这是h1标签<span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>123 <span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>&#x27;<br>// 调用 htmlEscape 进行转义<br>console.log(&#x27;编码后:&#x27;, tools.htmlEscape(htmlStr1))<br><br><br>运行结果<br><br>编码后: <span class="hljs-symbol">&amp;lt;</span>h1 title=<span class="hljs-symbol">&amp;quot;</span>xxx<span class="hljs-symbol">&amp;quot;</span><span class="hljs-symbol">&amp;gt;</span>这是h1标签<span class="hljs-symbol">&amp;lt;</span>span<span class="hljs-symbol">&amp;gt;</span>123<span class="hljs-symbol">&amp;amp;</span>nbsp;<span class="hljs-symbol">&amp;lt;</span>/span<span class="hljs-symbol">&amp;gt;</span><span class="hljs-symbol">&amp;lt;</span>/h1<span class="hljs-symbol">&amp;gt;</span><br><br>解码 HTML 中的特殊字符<br><br>const htmlStr = &#x27;<span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">title</span>=<span class="hljs-string">&quot;xxx&quot;</span>&gt;</span>这是h1标签<span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>123<span class="hljs-symbol">&amp;nbsp;</span><span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>&#x27;<br><br><br>console.log(&#x27;解码后:&#x27;, tools.htmlUnEscape(htmlStr))<br><br><br>运行结果<br><br>解码后: `<span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">title</span>=<span class="hljs-string">&quot;xxx&quot;</span>&gt;</span>`这是h1标签 `<span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>`123<span class="hljs-symbol">&amp;nbsp;</span>`<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>`<br>PS H:\javascript-demo&gt;<br></code></pre></td></tr></table></figure>
</li>
<li><p><strong>在本地测试包的效果 demo.js</strong></p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><code class="hljs javascript"><span class="hljs-keyword">const</span> tools = <span class="hljs-built_in">require</span>(<span class="hljs-string">&#x27;./uni-tools/index&#x27;</span>)<br><br><span class="hljs-keyword">const</span> date = tools.<span class="hljs-title function_">dateFormat</span>(<span class="hljs-keyword">new</span> <span class="hljs-title class_">Date</span>())<br><br><span class="hljs-keyword">const</span> htmlStr = <span class="hljs-string">&#x27;&lt;h1 title=&quot;xxx&quot;&gt;这是h1标签&lt;span&gt;123&amp;nbsp;&lt;/span&gt;&lt;/h1&gt;&#x27;</span><br><br><span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(date)<br><span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">&#x27;原来的HTML:&#x27;</span>, htmlStr)<br><span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">&#x27;编码后:&#x27;</span>, tools.<span class="hljs-title function_">htmlEscape</span>(htmlStr))<br><span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">&#x27;解码后:&#x27;</span>, tools.<span class="hljs-title function_">htmlUnEscape</span>(tools.<span class="hljs-title function_">htmlEscape</span>(htmlStr)))<br></code></pre></td></tr></table></figure>
<blockquote>
<p>运行结果</p>
</blockquote>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs xml">2022-08-04 09:04:54<br>原来的HTML: <span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">title</span>=<span class="hljs-string">&quot;xxx&quot;</span>&gt;</span>这是h1标签<span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>123<span class="hljs-symbol">&amp;nbsp;</span><span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>h1&gt;                                                           123<span class="hljs-symbol">&amp;amp;</span>nbsp;<span class="hljs-symbol">&amp;lt;</span>/span<span class="hljs-symbol">&amp;gt;</span><span class="hljs-symbol">&amp;lt;</span>/h1<span class="hljs-symbol">&amp;gt;</span><br>编码后: <span class="hljs-symbol">&amp;lt;</span>h1 title=<span class="hljs-symbol">&amp;quot;</span>xxx<span class="hljs-symbol">&amp;quot;</span><span class="hljs-symbol">&amp;gt;</span>这是h1标签<span class="hljs-symbol">&amp;lt;</span>span<span class="hljs-symbol">&amp;gt;</span>123<span class="hljs-symbol">&amp;amp;</span>nbsp;<span class="hljs-symbol">&amp;lt;</span>/span<span class="hljs-symbol">&amp;gt;</span><span class="hljs-symbol">&amp;lt;</span>/h1<span class="hljs-symbol">&amp;gt;</span><br>解码后: <span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">title</span>=<span class="hljs-string">&quot;xxx&quot;</span>&gt;</span>这是h1标签<span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>123<span class="hljs-symbol">&amp;nbsp;</span><span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span><br></code></pre></td></tr></table></figure></li>
</ol>
<h3 id="4-4-5-将自定义的包发布到-npm-官方"><a href="#4-4-5-将自定义的包发布到-npm-官方" class="headerlink" title="4.4.5 将自定义的包发布到 npm 官方"></a>4.4.5 将自定义的包发布到 npm 官方</h3><p><strong>第一步，注册 npm 账号</strong><br>访问 npm 官方注册页面：<a target="_blank" rel="noopener" href="https://www.npmjs.com/signup">https://www.npmjs.com/signup</a>，填写注册信息（需进行邮箱验证）</p>
<p><strong>第二步，切换 npm 镜像源到官方，否则会无法发布包到官网</strong><br>这里使用之前安装的 nrm 小工具直接切换npm镜像为 npm 官方就可以了</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs shell">nrm use npm<br></code></pre></td></tr></table></figure>

<p><strong>第三步，登录 npm 账号</strong><br>首先在官网登录 npm 账号进行二次身份验证 <a target="_blank" rel="noopener" href="https://www.npmjs.com/">https://www.npmjs.com/</a><br><img src="https://img-blog.csdnimg.cn/37ceee55e4824ce8a0ac9d55eb94e65e.png" srcset="/img/loading.gif" lazyload alt="在这里插入图片描述"></p>
<p>二次认证开启后会生成一串字符串密钥，记得保存这个密钥，之后在登录时需要<br><img src="https://img-blog.csdnimg.cn/4291807d4d6c4d8492bd9ae95c097e60.png" srcset="/img/loading.gif" lazyload alt="在这里插入图片描述"></p>
<p>npm 账号注册完成后，可以在终端执行 npm login 命令，依次输入用户名、密码、邮箱后，终端会提示进入到一个网站进行验证，点击验证即可<br><img src="https://img-blog.csdnimg.cn/a9ee8cce4a5e4ac499828afaa48e51ee.png" srcset="/img/loading.gif" lazyload alt="在这里插入图片描述"></p>
<p>验证成功后会返回一串数字作为本次的登录密码<br><img src="https://img-blog.csdnimg.cn/4b9b5e56cac340f28ce659fb5a10ad32.png" srcset="/img/loading.gif" lazyload alt="在这里插入图片描述"></p>
<p>将该密码复制到终端即可，最终登录成功的结果如下：</p>
<p><img src="https://img-blog.csdnimg.cn/b4112dc2af55432d8dd8a62dc1d58db3.png" srcset="/img/loading.gif" lazyload alt="在这里插入图片描述"></p>
<p><strong>第四步，将包发布到 npm 官方</strong><br>注：包名不能和现有的重复，如果重复了会发布失败</p>
<p>发布前，将终端所在位置切换到 npm 包所在的根目录</p>
<p><img src="https://img-blog.csdnimg.cn/1867e9d52eab4b6e85934685c1eb32c1.png" srcset="/img/loading.gif" lazyload alt="在这里插入图片描述"></p>
<p>切换终端位置到包所在的目录后，执行 npm publish 命令发布</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs shell">npm publish<br></code></pre></td></tr></table></figure>

<p>发布命令执行后会提示需进入网站里进行身份验证，和登录时一样<br>如果出现重名就会出现 一堆 ERR! ，主要有 </p>
<blockquote>
<p>You do not have permission to publish “xxx”</p>
</blockquote>
<p>这里我之前定义的 uni-tools 重名了，后来改成了 unirithe-demo 就可以发布~<br><img src="https://img-blog.csdnimg.cn/ba6508230b514612b0d6d601724bc87e.png" srcset="/img/loading.gif" lazyload alt="在这里插入图片描述"></p>
<h3 id="4-4-6-测试发布的包"><a href="#4-4-6-测试发布的包" class="headerlink" title="4.4.6 测试发布的包"></a>4.4.6 测试发布的包</h3><p>接下来新建一个文件夹，测试一下能否从官方安装自己之前提交的包<br>执行安装的命令</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs shell">npm install unirithe-demo@1.0.0<br></code></pre></td></tr></table></figure>
<p>安装成功后，项目结构变成了下图，之前上传的包下载到了node_modules 文件夹中<br><img src="https://img-blog.csdnimg.cn/753715266fae497bb469ce73be92efaa.png" srcset="/img/loading.gif" lazyload alt="在这里插入图片描述"></p>
<p>接下来在自定义的demo.js脚本里使用这个包</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><code class="hljs javascript"><span class="hljs-keyword">const</span> demo = <span class="hljs-built_in">require</span>(<span class="hljs-string">&#x27;unirithe-demo&#x27;</span>)<br><br><span class="hljs-keyword">const</span> date = demo.<span class="hljs-title function_">dateFormat</span>(<span class="hljs-keyword">new</span> <span class="hljs-title class_">Date</span>())<br><br><span class="hljs-keyword">const</span> htmlStr = <span class="hljs-string">&#x27;&lt;h1 title=&quot;xxx&quot;&gt;这是h1标签&lt;span&gt;123&amp;nbsp;&lt;/span&gt;&lt;/h1&gt;&#x27;</span><br><br><span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(date)<br><span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">&#x27;原来的HTML:&#x27;</span>, htmlStr)<br><span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">&#x27;编码后:&#x27;</span>, demo.<span class="hljs-title function_">htmlEscape</span>(htmlStr))<br><span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">&#x27;解码后:&#x27;</span>, demo.<span class="hljs-title function_">htmlUnEscape</span>(demo.<span class="hljs-title function_">htmlEscape</span>(htmlStr)))<br></code></pre></td></tr></table></figure>
<p>运行结果：<br><img src="https://img-blog.csdnimg.cn/23a203be92754e5f848f364c63378ae8.png" srcset="/img/loading.gif" lazyload alt="在这里插入图片描述"></p>
<p>和之前是一样的，不同的是，其他人也可以直接使用 npm install [包名] 安装我们之前发布的这个模块</p>
<h2 id="4-5-包的卸载"><a href="#4-5-包的卸载" class="headerlink" title="4.5 包的卸载"></a>4.5 包的卸载</h2><p>除了上传包以外，我们还可以删除包，执行 npm unpublish 命令即可，接下来卸载之前上传的包（这个命令也是需要二次验证的，和之前登录、发布包的过程一样）：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs shell">npm unpublish unirithe-demo --force<br></code></pre></td></tr></table></figure>
<p>卸载成功后：</p>
<p><img src="https://img-blog.csdnimg.cn/bdd7069b609d4976b702c57f10c54e26.png" srcset="/img/loading.gif" lazyload alt="在这里插入图片描述"></p>
<p>注：npm 官方对于包的管理是有一些规则的，官方文档：<a target="_blank" rel="noopener" href="https://docs.npmjs.com/policies/unpublish">https://docs.npmjs.com/policies/unpublish</a></p>
<ul>
<li>unpublish 支持删除 72 小时以内发布的包</li>
<li>unpublish 支持删除超过 72个小时 不过需同时满足以下条件：<ul>
<li>npm 官方其他的包没有依赖当前的包</li>
<li>上周的下载量少于 300 次</li>
</ul>
</li>
</ul>
<h2 id="4-5-模块的加载机制"><a href="#4-5-模块的加载机制" class="headerlink" title="4.5 模块的加载机制"></a>4.5 模块的加载机制</h2><h3 id="4-5-1-优先从缓存中加载"><a href="#4-5-1-优先从缓存中加载" class="headerlink" title="4.5.1 优先从缓存中加载"></a>4.5.1 优先从缓存中加载</h3><p>模块在第一次加载后会被缓存，这说明多次调用 require() 方法不会导致模块代码被执行多次。<br>不论是 内置模块、用户自定义模块、第三方模块，它们都会优先从缓存中加载，从而提高模块的加载效率。</p>
<h2 id="4-6-内置模块的加载机制"><a href="#4-6-内置模块的加载机制" class="headerlink" title="4.6 内置模块的加载机制"></a>4.6 内置模块的加载机制</h2><p>内置模块是由 Node.js 官方提供的模块，模块的加载优先级最高，例如：即使在 node_modules 里存在 fs 模块，在调用时候 require(‘fs’) 仍然会加载内置的 fs 模块，而不会加载 node_modules 里的第三方模块。</p>
<h2 id="4-7-自定义模块的加载机制"><a href="#4-7-自定义模块的加载机制" class="headerlink" title="4.7 自定义模块的加载机制"></a>4.7 自定义模块的加载机制</h2><p>使用 require() 加载自定义模块时，必须指定以 <code>./</code>或者 <code>../</code>开头的路径标识符。<br>在加载自定义模块时，若没有指定 <code>./</code>或者 <code>../</code>这样的路径标识符，那么 node 则会将其作为 内置模块或第三方模块进行加载。<br>若在 require() 引入自定义模块时，忽略了文件的 <code>.js</code>扩展名，那么 Node.js 会按顺序分别尝试加载以下的文件：</p>
<ol>
<li>按照确切的文件名加载</li>
<li>补全 .js 扩展名进行加载</li>
<li>补全 .json 扩展名进行加载</li>
<li>补全 .node 扩展名进行加载</li>
<li>加载失败，终端报错</li>
</ol>
<h2 id="4-8-第三方模块的加载机制"><a href="#4-8-第三方模块的加载机制" class="headerlink" title="4.8 第三方模块的加载机制"></a>4.8 第三方模块的加载机制</h2><p>若 require(‘xxx’) 请求的模块名既不是内置模块，也不是 <code>./</code>或 <code>../</code>开头的模块，那么 Node.js 会从当前模块的父目录开始，尝试从 <code>/node_modules</code>文件夹中加载第三方模块</p>
<p>若没有找到对应第三方模块，则会移动到上一层父目录中进行加载，直到文件系统的根目录</p>
<p>【例】在 <code>c:\User\uni\project\demo.js</code> 文件里调用了 <code>require(&#39;tools&#39;)</code>，则Node.js会遵循以下顺序查找：</p>
<ol>
<li><code>c:\User\uni\project\node_modules\tools</code></li>
<li><code>c:\User\uni\node_modules\tools</code></li>
<li><code>c:\User\node_modules\tools</code></li>
<li><code>c:\node_modules\tools</code></li>
</ol>
<h2 id="4-9-目录作为模块"><a href="#4-9-目录作为模块" class="headerlink" title="4.9 目录作为模块"></a>4.9 目录作为模块</h2><p>当把目录作为模块标识符，传递给 require() 进行加载的时候，有三种加载方式：</p>
<ol>
<li>在被加载的目录下查找一个叫做 <code>package.json</code>的文件，并寻找 main 属性，作为require() 加载的入口</li>
<li>若目录里没有 package.json 文件，或 main 入口不存在或无法解析，那么 Node.js 将会试图加载目录下的 index.js 文件</li>
<li>若以上两种方式都失败，那么 Node.js 会提示 Error: Cannot find module ‘xxx’</li>
</ol>
<h1 id="5-Express"><a href="#5-Express" class="headerlink" title="5. Express"></a>5. Express</h1><hr>
<h2 id="5-1-Express-简介"><a href="#5-1-Express-简介" class="headerlink" title="5.1 Express 简介"></a>5.1 Express 简介</h2><p><a target="_blank" rel="noopener" href="https://www.expressjs.com.cn/">Express</a> 是基于 Node.js 平台，快速、开放、极简的 Web 开发框架。<br>通俗理解：Express 的作用和 Node.js 内置的 http 模块类似，是专门用来创建 Web 服务器的。<br>Express 本质：npm上的第三方包，提供了快速创建 Web 服务器的便捷方法</p>
<p>Node.js 第三方包 Express 与 Node.js 内置的 http 模块比较：</p>
<ul>
<li>http 和 Express 都能创建 Web 服务器</li>
<li>http 内置模块用起来比较复杂，开发效率没有 Express 高，因为 Express 是基于 http 进行开发的</li>
<li>http 与 Express 的关系类似 JavaScript 中 Web APIs 和 JQuery 的关系，都是基于前者进一步封装出来的。</li>
</ul>
<p>Express 的作用：</p>
<ul>
<li>开发 Web 网站服务器：专门对外提供 Web 网页资源的服务器</li>
<li>API 接口服务器：专门对外提供 API 接口的服务器</li>
</ul>
<h2 id="5-2-Express-基本使用"><a href="#5-2-Express-基本使用" class="headerlink" title="5.2 Express 基本使用"></a>5.2 Express 基本使用</h2><p>查看 express 所有版本</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs shell">npm view express versions<br></code></pre></td></tr></table></figure>
<p><img src="https://img-blog.csdnimg.cn/f14dfea650a54d8595fbf283dcd1a99b.png" srcset="/img/loading.gif" lazyload alt="在这里插入图片描述"></p>
<p>目前 Express 最新版本为 5.0.0 ，为了稳定起见，通常安装旧一点的版本，比如4.17.1</p>
<ol>
<li><p><strong>安装 Express 旧版本</strong></p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs shell">npm i express@4.17.1<br></code></pre></td></tr></table></figure>
</li>
<li><p><strong>创建基本的 Web 服务器</strong></p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs javascript"><span class="hljs-keyword">const</span> express = <span class="hljs-built_in">require</span>(<span class="hljs-string">&#x27;express&#x27;</span>)<br><br><span class="hljs-keyword">const</span> app = <span class="hljs-title function_">express</span>()<br><br>app.<span class="hljs-title function_">listen</span>(<span class="hljs-number">80</span>, <span class="hljs-function">() =&gt;</span> &#123;<br>    <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">&#x27;express server running at http://127.0.0.1&#x27;</span>)<br>&#125;)<br></code></pre></td></tr></table></figure>
</li>
<li><p><strong>监听 GET 请求</strong></p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs javascript"><span class="hljs-comment">// 参数1: 客户端请求的 URL 地址</span><br><span class="hljs-comment">// 参数2: 请求对应的处理函数</span><br><span class="hljs-comment">//				req:  请求对象  (包含了与请求相关的属性与方法)</span><br><span class="hljs-comment">//				res:	响应对象 (包含了与响应相关的属性与方法)</span><br>app.<span class="hljs-title function_">get</span>(<span class="hljs-string">&#x27;请求URL&#x27;</span>, <span class="hljs-keyword">function</span>(<span class="hljs-params">req, res</span>) &#123;&#125; <span class="hljs-comment">/* 处理函数 */</span>)<br></code></pre></td></tr></table></figure>

</li>
<li><p><strong>监听 POST 请求</strong></p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs javascript"><span class="hljs-comment">// 参数1: 客户端请求的 URL 地址</span><br><span class="hljs-comment">// 参数2: 请求对应的处理函数</span><br><span class="hljs-comment">//				req:  请求对象  (包含了与请求相关的属性与方法)</span><br><span class="hljs-comment">//				res:	响应对象 (包含了与响应相关的属性与方法)</span><br>app.<span class="hljs-title function_">post</span>(<span class="hljs-string">&#x27;请求URL&#x27;</span>, <span class="hljs-keyword">function</span>(<span class="hljs-params">req, res</span>) &#123;&#125; <span class="hljs-comment">/* 处理函数 */</span>)<br></code></pre></td></tr></table></figure>
</li>
<li><p><strong>把内容响应给客户端</strong></p>
</li>
</ol>
<p>通过 res.send() 方法，可以把处理好的内容发送给客户端：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><code class="hljs javascript">app.<span class="hljs-title function_">get</span>(<span class="hljs-string">&#x27;/user&#x27;</span>, <span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> &#123;<br>    <span class="hljs-comment">// 向客户端发送 JSON 对象</span><br>    res.<span class="hljs-title function_">send</span>(&#123; <span class="hljs-attr">name</span>: <span class="hljs-string">&#x27;uni&#x27;</span>&#125;)<br>&#125;)<br><br>app.<span class="hljs-title function_">post</span>(<span class="hljs-string">&#x27;/user&#x27;</span>, <span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> &#123;<br>    <span class="hljs-comment">// 项客户端发送文本内容</span><br>    res.<span class="hljs-title function_">send</span>(<span class="hljs-string">&#x27;请求成功&#x27;</span>)<br>&#125;)<br></code></pre></td></tr></table></figure>

<ol start="6">
<li><strong>获取 URL 中携带的查询参数</strong></li>
</ol>
<p>通过 req.query 对象，可以访问到客户端通过查询字符串的形式，发送到服务器的参数</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs javascript">app.<span class="hljs-title function_">get</span>(<span class="hljs-string">&#x27;/&#x27;</span>, <span class="hljs-function">(<span class="hljs-params">req, resp</span>) =&gt;</span> &#123;<br>   <span class="hljs-comment">// req.query 默认是一个空对象</span><br>   <span class="hljs-comment">// req.query 是指浏览器使用 url?name=uni&amp;age=22 这种查询字符串的形式</span><br>   <span class="hljs-comment">// req.query.name 或 req.query.age 可直接获取当上面这种传值</span><br>   <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(req.<span class="hljs-property">query</span>)<br>&#125;<br></code></pre></td></tr></table></figure>

<ol start="7">
<li><strong>获取 URL 中的动态参数</strong></li>
</ol>
<p>通过 req.params 对象，可以访问到 URL 中，通过 : 匹配到的动态参数</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs javascript">app.<span class="hljs-title function_">get</span>(<span class="hljs-string">&#x27;/user/:id&#x27;</span>, <span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> &#123;<br>    <span class="hljs-comment">// req.params 是动态匹配到的 URL 参数, 默认也是一个空对象</span><br>    <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(req.<span class="hljs-property">params</span>.<span class="hljs-property">id</span>)<br>&#125;)<br></code></pre></td></tr></table></figure>

<h2 id="5-3-托管静态资源"><a href="#5-3-托管静态资源" class="headerlink" title="5.3 托管静态资源"></a>5.3 托管静态资源</h2><ol>
<li><strong>express.static()</strong></li>
</ol>
<p>express.static() 方法可以非常方便地创建一个静态资源服务器，例如：开放 public 目录下的文件，通过 <code>url/images/1.jpg</code> 可访问到 <code>url/public/images/1.jpg</code> 文件</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs javascript">app.<span class="hljs-title function_">use</span>(express.<span class="hljs-title function_">static</span>(<span class="hljs-string">&#x27;public&#x27;</span>))<br></code></pre></td></tr></table></figure>

<ol start="2">
<li><p><strong>托管多个静态资源目录</strong></p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs javascript">app.<span class="hljs-title function_">use</span>(express.<span class="hljs-title function_">static</span>(<span class="hljs-string">&#x27;public&#x27;</span>))<br>app.<span class="hljs-title function_">use</span>(express.<span class="hljs-title function_">static</span>(<span class="hljs-string">&#x27;files&#x27;</span>))<br></code></pre></td></tr></table></figure>
<p>访问静态资源文件时，express.static() 函数会根据目录的添加顺序查找所需的文件</p>
</li>
<li><p><strong>挂在路径前缀</strong></p>
</li>
</ol>
<p>express().use()方法除了接收express.static参数外，还支持接收前缀字符串，依此实现在访问静态资源文件时访问固定的前缀路径，例如：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs javascript">app.<span class="hljs-title function_">use</span>(<span class="hljs-string">&#x27;/public&#x27;</span>, express.<span class="hljs-title function_">static</span>(<span class="hljs-string">&#x27;public&#x27;</span>))<br></code></pre></td></tr></table></figure>
<p>这样在访问 public 文件夹里的静态资源时就需要添加 &#x2F;public 前缀了</p>
<h2 id="5-4-nodemon"><a href="#5-4-nodemon" class="headerlink" title="5.4 nodemon"></a>5.4 nodemon</h2><p>在编写调试 Node.js 项目时，若修改了项目的代码，则需频繁地关闭、开启。<br><a target="_blank" rel="noopener" href="https://www.npmjs.com/package/nodemon">nodemon </a>可以很好的解决这个问题，它能监听项目文件的变动，当代码被修改后，nodemon 会自动重启项目，极大方便了开发和调试。</p>
<p><strong>安装 nodemon</strong></p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs shell">npm install -g nodemon<br></code></pre></td></tr></table></figure>

<p><strong>使用 nodemon</strong><br>之前执行脚本文件是通过node命令，例如 node demo.js ，在安装 nodemon 工具后，我们可以使用 nodemon 命令来执行 js脚本，这样就能使用 nodemon 支持的项目文件监听了。</p>
<h2 id="5-5-Express-路由"><a href="#5-5-Express-路由" class="headerlink" title="5.5 Express 路由"></a>5.5 Express 路由</h2><p>路由，广义上来说就是映射关系，在 Express 中，路由是指客户端的请求与服务器处理函数之间的映射关系。</p>
<p>Express 中的路由分为三部分组成，分别是请求的类型、请求的 URL地址、处理函数，格式如下：</p>
<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs json">app.METHOD(PATH<span class="hljs-punctuation">,</span> HANDLER)<br></code></pre></td></tr></table></figure>
<p>【例】get、post请求的路由</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs javascript">app.<span class="hljs-title function_">get</span>(<span class="hljs-string">&#x27;/&#x27;</span>, <span class="hljs-keyword">function</span>(<span class="hljs-params">req, res</span>)&#123;<br>  res.<span class="hljs-title function_">send</span>(<span class="hljs-string">&#x27;get hello&#x27;</span>)<br>&#125;)<br><br>app.<span class="hljs-title function_">post</span>(<span class="hljs-string">&#x27;/&#x27;</span>, <span class="hljs-keyword">function</span>(<span class="hljs-params">req, res</span>)&#123;<br>   resp.<span class="hljs-title function_">send</span>(<span class="hljs-string">&#x27;post hello&#x27;</span>) <br>&#125;)<br></code></pre></td></tr></table></figure>
<p><strong>路由的匹配过程：</strong><br>每当一个请求到达服务器后，需先经过路由的匹配，只有匹配成功后，才会调用对象的处理函数。在匹配时，会按照路由的顺序进行匹配，若请求类型和请求URL同时匹配成功，那么 Express 则会将这次请求转交给对应的 function 函数进行处理。</p>
<p><strong>路由的模块化：</strong><br>为方便对路由进行模块化管理，Express 不建议将路由直接挂载到 app 上，而是推荐将路由抽离为单独的模块。<br>将路由抽离为单独模块的步骤如下：</p>
<ol>
<li>创建路由模块对应的 <code>.js</code>文件</li>
<li>调用 express.Router() 函数创建路由对象</li>
<li>由路由对象上挂载具体的路由</li>
<li>使用 moudule.exports 向外共享路由对象</li>
<li>使用 app.use() 函数注册路由模块</li>
</ol>
<p>例如：</p>
<p>定义路由模块：my-router.js</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs javascript"><span class="hljs-keyword">const</span> express = <span class="hljs-built_in">require</span>(<span class="hljs-string">&#x27;express&#x27;</span>)		<span class="hljs-comment">// 1. 导入 express</span><br><span class="hljs-keyword">const</span> router = express.<span class="hljs-title class_">Router</span>()				<span class="hljs-comment">// 2. 创建路由对象</span><br><br>router.<span class="hljs-title function_">get</span>(<span class="hljs-string">&#x27;/&#x27;</span>, <span class="hljs-keyword">function</span>(<span class="hljs-params">req, res</span>)&#123;		<span class="hljs-comment">// 3. 挂载路由</span><br>    res.<span class="hljs-title function_">send</span>(<span class="hljs-string">&#x27;server running&#x27;</span>)<br>&#125;)<br><br><span class="hljs-variable language_">module</span>.<span class="hljs-property">exports</span> = router								<span class="hljs-comment">// 4. 导出路由对象</span><br></code></pre></td></tr></table></figure>

<p>使用路由模块：demo.js</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs javascript"><span class="hljs-keyword">const</span> express = <span class="hljs-built_in">require</span>(<span class="hljs-string">&#x27;express&#x27;</span>)<br><span class="hljs-keyword">const</span> app = <span class="hljs-title function_">express</span>()<br><span class="hljs-comment">// 导入路由模块</span><br><span class="hljs-keyword">const</span> router = <span class="hljs-built_in">require</span>(<span class="hljs-string">&#x27;./my-router.js&#x27;</span>)<br><span class="hljs-comment">// 使用 app.use() 注册路由模块</span><br>app.<span class="hljs-title function_">use</span>(router)<br></code></pre></td></tr></table></figure>
<p>Express 的 路由和静态资源配置类似，支持添加前缀，比如：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs javascript">app.<span class="hljs-title function_">use</span>(<span class="hljs-string">&#x27;/api&#x27;</span>, router)<br></code></pre></td></tr></table></figure>

<h2 id="5-6-Express-中间件"><a href="#5-6-Express-中间件" class="headerlink" title="5.6 Express 中间件"></a>5.6 Express 中间件</h2><p>中间件 （Middleware），特指业务流程的中间处理环节。<br>当一个请求到达 Express 的服务器后，可连续调用多个中间件，从而对这次请求进行预处理。<br>Express 的中间件本质上就是一个 function 处理函数，格式如下：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs javascript">app.<span class="hljs-title function_">METHOD</span>(<span class="hljs-variable constant_">URL</span>, <span class="hljs-title function_">funcion</span>(<span class="hljs-params">req, resp, next</span>)&#123;<br>   <span class="hljs-title function_">next</span>()           <br>&#125;)<br></code></pre></td></tr></table></figure>
<p>注：中间件函数的形参列表中，必须包含 next 参数，而路由处理函数中只包含 req 和 resp</p>
<p>next 函数的作用：把流传关系给下一个中间件或者路由</p>
<p>Express 的中间件分为全局和局部这两种<br><strong>全局中间件</strong><br>全局中间件是指：客户端发起的任何请求，到达服务器后，都会触发的中间件，例如：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs javascript"><span class="hljs-keyword">const</span> mw =  <span class="hljs-keyword">function</span>(<span class="hljs-params">req, resp, next</span>)&#123;<br>   <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">&#x27;this is a middle ware function&#x27;</span>)<br>   <span class="hljs-title function_">next</span>()<br>&#125;<br><br><span class="hljs-comment">// 设置全局生效的中间件</span><br>app.<span class="hljs-title function_">use</span>(mw)<br></code></pre></td></tr></table></figure>

<p><strong>局部中间件</strong><br>局部中间件是指不适用 app.use() 指定中间件函数，而是使用 app.METHOD来绑定，例如：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs javascript"><span class="hljs-keyword">const</span> mw =  <span class="hljs-keyword">function</span>(<span class="hljs-params">req, resp, next</span>)&#123;<br>   <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">&#x27;this is a middle ware function&#x27;</span>)<br>   <span class="hljs-title function_">next</span>()<br>&#125;<br><br>app.<span class="hljs-title function_">get</span>(<span class="hljs-string">&#x27;/&#x27;</span>, mv, <span class="hljs-keyword">function</span>(<span class="hljs-params">req, rsp</span>)&#123;<br>   <span class="hljs-comment">// ...</span><br>&#125;)<br></code></pre></td></tr></table></figure>
<p>局部中间件可以定义任意多个</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs javascript">app.<span class="hljs-title function_">get</span>(<span class="hljs-string">&#x27;/&#x27;</span>, mv1, mv2, <span class="hljs-keyword">function</span>(<span class="hljs-params">req, res</span>)&#123;<br>  <span class="hljs-comment">// ...</span><br>&#125;)<br><br>app.<span class="hljs-title function_">get</span>(<span class="hljs-string">&#x27;/&#x27;</span>, [mv1, mv2], <span class="hljs-keyword">function</span>(<span class="hljs-params">req, res</span>)&#123;<br>  <span class="hljs-comment">// ...</span><br>&#125;)<br></code></pre></td></tr></table></figure>

<p><strong>Express 中间件的分类：Express 官方把常见的中间件用法分成了五大类，分别是：</strong></p>
<ol>
<li>应用级别的中间件</li>
<li>路由级别的中间件</li>
<li>错误级别的中间件</li>
<li>Express 内置的中间件</li>
<li>第三方的中间件</li>
</ol>
<p>1、 <strong>应用级别的中间件</strong></p>
<p>通过 app.use() 或 app.get() 或 app.post()，绑定到 app 实例上的中间件叫做应用级别的中间件，代码实例如下：</p>
<p>2、 <strong>路由级别的中间件</strong></p>
<p>绑定到 express.Router() 实例上的中间件，称为路由级别的中间件，它的用法和应用级别中间件没有区别，只不过此类中间件是绑定到 router 实例上的。</p>
<p>3、<strong>错误级别的中间件</strong></p>
<p>错误级别中间件的作用：专门用来补货整个项目中发生的异常错误，从而防止项目异常崩溃的问题。错误级别中间件中必须有四个形参，分别是 (err, req, res, next)，通常定义在其他所有中间件的后面。</p>
<p>4、<strong>Express 内置的中间件</strong></p>
<p>从 Express 4.16.0 版本开始，Express 内置了三个常用的中间件：</p>
<ul>
<li>express.static，快速托管静态资源的内置中间件，例如：HTML文件、图片、CSS样式等</li>
<li>express.json，解析 JSON 格式的请求体数据</li>
<li>express.urlencoded，解析 URL-encoded 格式的请求体数据</li>
</ul>
<p>5、<strong>第三方中间件</strong></p>
<p>第三方中间件通过 npm install xxx 进行安装，在代码中通过 require(‘xxx’) 引入</p>
<h2 id="5-7-案例——自定义中间件"><a href="#5-7-案例——自定义中间件" class="headerlink" title="5.7 案例——自定义中间件"></a>5.7 案例——自定义中间件</h2><p>手动模拟一个类似 express.urlencoded 这样的中间件，作用是解析 POST 提交到服务器的表单数据，实现步骤：</p>
<ol>
<li>定义中间件</li>
<li>监听 req 的 data 事件</li>
<li>监听 req 的 end 事件</li>
<li>使用 querystring 模板解析请求体数据</li>
<li>将解析出来的数据挂载为 req.body</li>
<li>将自定义中间件封装为模块</li>
</ol>
<p>在中间件中，需监听 req 对象的 data 事件，来获取客户端发送到服务器的数据<br>若数据量比较大，无法一次性发送，那么客户端会把数据分割，分批次发送到服务器，所以 data 事件可能会触发多次，获取到的数据只是完整数据的一部分，需手动对接收的数据进行拼接。</p>
<p>在请求体数据接收完毕后，会自动触发 req 的 end 事件，因此可以在 req 的 end事件里，拿到并处理完整的请求体数据。</p>
<p><strong>项目结构</strong></p>
<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs json">|- main.js 应用的启动脚本<br><br>|- custom-body-parser.js	自定义的中间件模块<br></code></pre></td></tr></table></figure>


<p><code>custom-body-parser.js</code></p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><code class="hljs javascript"><span class="hljs-comment">// 导入  Node.js 内置的模块</span><br><span class="hljs-keyword">const</span> <span class="hljs-title function_">bodyParser</span> = (<span class="hljs-params">req, resp, next</span>) =&gt; &#123;<br>    <span class="hljs-keyword">let</span> body = <span class="hljs-string">&#x27;&#x27;</span><br><br>    <span class="hljs-comment">// 监听req的data事件 </span><br>    req.<span class="hljs-title function_">on</span>(<span class="hljs-string">&#x27;data&#x27;</span>, <span class="hljs-function">(<span class="hljs-params">chunk</span>) =&gt;</span>&#123;<br>        body += chunk<br>    &#125;)<br><br>    <span class="hljs-comment">// 监听req的end事件</span><br>    req.<span class="hljs-title function_">on</span>(<span class="hljs-string">&#x27;end&#x27;</span>, <span class="hljs-function">() =&gt;</span> &#123;<br>        <span class="hljs-comment">// <span class="hljs-doctag">TODO:</span> 把字符串格式的请求体数据, 解析成对象格式</span><br>        req.<span class="hljs-property">body</span> = <span class="hljs-title class_">JSON</span>.<span class="hljs-title function_">parse</span>(body)<br>        <span class="hljs-title function_">next</span>()<br>    &#125;)<br>&#125;<br><span class="hljs-comment">// 导出</span><br><span class="hljs-variable language_">module</span>.<span class="hljs-property">exports</span> = bodyParser<br></code></pre></td></tr></table></figure>
<p><code>main.js</code></p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><code class="hljs javascript"><span class="hljs-keyword">const</span> express = <span class="hljs-built_in">require</span>(<span class="hljs-string">&#x27;express&#x27;</span>)<br><span class="hljs-keyword">const</span> app = <span class="hljs-title function_">express</span>()<br><br><span class="hljs-comment">// 导入自定义的中间件模块</span><br><span class="hljs-keyword">const</span> customBodyParser = <span class="hljs-built_in">require</span>(<span class="hljs-string">&#x27;./custom-body-parser&#x27;</span>)<br><br>app.<span class="hljs-title function_">post</span>(<span class="hljs-string">&#x27;/user&#x27;</span>, customBodyParser, <span class="hljs-function">(<span class="hljs-params">req, resp</span>) =&gt;</span> &#123;<br>    <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">&#x27;获取到请求体数据:&#x27;</span>, req.<span class="hljs-property">body</span>)<br>    resp.<span class="hljs-title function_">send</span>(req.<span class="hljs-property">body</span>)<br>&#125;)<br>app.<span class="hljs-title function_">listen</span>(<span class="hljs-number">80</span>, <span class="hljs-function">() =&gt;</span> &#123;<br>    <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">&#x27;express server running at http://127.0.0.1&#x27;</span>)<br>&#125;)<br></code></pre></td></tr></table></figure>

<p>在启动后使用 Postman 进行测试：<a target="_blank" rel="noopener" href="http://localhost/user%EF%BC%8C%E6%95%88%E6%9E%9C%E5%A6%82%E4%B8%8B%EF%BC%9A">http://localhost/user，效果如下：</a></p>
<p><img src="https://img-blog.csdnimg.cn/17de54b3c5044995a4c2398dd81b4411.png" srcset="/img/loading.gif" lazyload alt="在这里插入图片描述"></p>
<h2 id="5-8-案例——开发登录接口"><a href="#5-8-案例——开发登录接口" class="headerlink" title="5.8 案例——开发登录接口"></a>5.8 案例——开发登录接口</h2><p><strong>项目结构</strong></p>
<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs json">|- apiRouter.js	路由脚本文件<br>|- main.js		  应用程序启动的脚本文件<br><br>|- index.html 	测试接口访问的 HTML 页面<br></code></pre></td></tr></table></figure>


<p><code>apiRouter.js</code></p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><code class="hljs javascript"><span class="hljs-keyword">const</span> express = <span class="hljs-built_in">require</span>(<span class="hljs-string">&#x27;express&#x27;</span>)<br><br><span class="hljs-keyword">const</span> router = express.<span class="hljs-title class_">Router</span>()<br><br><span class="hljs-comment">// Response : 响应</span><br><span class="hljs-keyword">function</span> <span class="hljs-title function_">R</span>(<span class="hljs-params">code = <span class="hljs-string">&#x27;200&#x27;</span>, msg = <span class="hljs-string">&#x27;&#x27;</span>, data = <span class="hljs-literal">null</span></span>) &#123;<br>    <span class="hljs-keyword">return</span> &#123;<br>        code,<br>        msg,<br>        data<br>    &#125;<br>&#125;<br>router.<span class="hljs-title function_">get</span>(<span class="hljs-string">&#x27;/&#x27;</span>, <span class="hljs-function">(<span class="hljs-params">req, resp</span>) =&gt;</span> &#123;<br>    resp.<span class="hljs-title function_">send</span>(<span class="hljs-title function_">R</span>(<span class="hljs-number">200</span>, <span class="hljs-string">&#x27;访问成功, 目前有[GET]/user 和 [POST]/login 这两个接口&#x27;</span>, <span class="hljs-literal">null</span>))<br>&#125;)<br>router.<span class="hljs-title function_">get</span>(<span class="hljs-string">&#x27;/user&#x27;</span>, <span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> &#123;<br>    res.<span class="hljs-title function_">send</span>(<span class="hljs-title function_">R</span>(<span class="hljs-number">200</span>, <span class="hljs-string">&#x27;查询成功&#x27;</span>, <br>        &#123;<span class="hljs-attr">name</span>: <span class="hljs-string">&#x27;admin&#x27;</span>, <span class="hljs-attr">password</span>: <span class="hljs-string">&#x27;123456&#x27;</span>&#125;,<br>    ))<br>&#125;)<br>router.<span class="hljs-title function_">post</span>(<span class="hljs-string">&#x27;/login&#x27;</span>, <span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> &#123;<br>    <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">&#x27;@&#x27;</span>,req.<span class="hljs-property">body</span>)<br>    <span class="hljs-keyword">const</span> user = &#123;<br>        <span class="hljs-attr">name</span>: req.<span class="hljs-property">body</span>.<span class="hljs-property">name</span> || <span class="hljs-string">&#x27;&#x27;</span>,<br>        password : req.<span class="hljs-property">body</span>.<span class="hljs-property">password</span> || <span class="hljs-string">&#x27;&#x27;</span><br>    &#125;<br><br>    <span class="hljs-keyword">if</span>(user.<span class="hljs-property">name</span> == <span class="hljs-string">&#x27;admin&#x27;</span> &amp;&amp; user.<span class="hljs-property">password</span> == <span class="hljs-string">&#x27;123456&#x27;</span>)&#123;<br>        res.<span class="hljs-title function_">send</span>(<span class="hljs-title function_">R</span>(<span class="hljs-number">200</span>, <span class="hljs-string">&#x27;登录成功&#x27;</span>, &#123;<span class="hljs-attr">token</span>: <span class="hljs-string">&#x27;abcdefg&#x27;</span>&#125;))<br>    &#125; <span class="hljs-keyword">else</span>&#123;<br>        res.<span class="hljs-title function_">send</span>(<span class="hljs-title function_">R</span>(<span class="hljs-number">400</span>, <span class="hljs-string">&#x27;账号或密码错误&#x27;</span>))<br>    &#125;<br>&#125;)<br><br><span class="hljs-variable language_">module</span>.<span class="hljs-property">exports</span> = router<br></code></pre></td></tr></table></figure>

<p><code>main.js</code></p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><code class="hljs javascript"><span class="hljs-comment">//-------------------------------- 第三方包</span><br><span class="hljs-keyword">const</span> express = <span class="hljs-built_in">require</span>(<span class="hljs-string">&#x27;express&#x27;</span>)<br><br><span class="hljs-keyword">const</span> bodyParser = <span class="hljs-built_in">require</span>(<span class="hljs-string">&#x27;body-parser&#x27;</span>)<br><span class="hljs-comment">//-------------------------------- 自定义的包</span><br><span class="hljs-keyword">const</span> router = <span class="hljs-built_in">require</span>(<span class="hljs-string">&#x27;./apiRouter&#x27;</span>)<br><br><span class="hljs-keyword">const</span> app = <span class="hljs-title function_">express</span>()<br><br><br>app.<span class="hljs-title function_">use</span>(bodyParser.<span class="hljs-title function_">urlencoded</span>(&#123; <span class="hljs-attr">extended</span>: <span class="hljs-literal">false</span> &#125;))<br>app.<span class="hljs-title function_">use</span>(router)<br>app.<span class="hljs-title function_">listen</span>(<span class="hljs-string">&#x27;80&#x27;</span>, <span class="hljs-function">() =&gt;</span>&#123;<br>    <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">&#x27;server is running at http://127.0.0.1:80&#x27;</span>)<br>&#125;)<br></code></pre></td></tr></table></figure>
<p><code>index.html</code></p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br></pre></td><td class="code"><pre><code class="hljs html"><span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-keyword">html</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">&quot;en&quot;</span>&gt;</span><br>  <span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">&quot;UTF-8&quot;</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">&quot;viewport&quot;</span> <span class="hljs-attr">content</span>=<span class="hljs-string">&quot;width=device-width, initial-scale=1.0&quot;</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>Document<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">&quot;https://cdn.staticfile.org/jquery/3.6.0/jquery.min.js&quot;</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span><br>  <span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span><br>  <span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onclick</span>=<span class="hljs-string">&quot;queryUser()&quot;</span>&gt;</span>查询用户<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">form</span> <span class="hljs-attr">id</span>=<span class="hljs-string">&quot;loginForm&quot;</span>&gt;</span><br>      用户名: <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">name</span>=<span class="hljs-string">&quot;name&quot;</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">br</span>&gt;</span><br>      密码:<span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">name</span>=<span class="hljs-string">&quot;password&quot;</span> <span class="hljs-attr">type</span>=<span class="hljs-string">&quot;password&quot;</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">br</span>&gt;</span><br>      <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">type</span>=<span class="hljs-string">&quot;button&quot;</span> <span class="hljs-attr">onclick</span>=<span class="hljs-string">&quot;login()&quot;</span>&gt;</span>登录<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span><br>    <span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="language-javascript"></span><br><span class="language-javascript">      <span class="hljs-keyword">function</span> <span class="hljs-title function_">queryUser</span>(<span class="hljs-params"></span>)&#123;</span><br><span class="language-javascript">        $.<span class="hljs-title function_">ajax</span>(&#123;</span><br><span class="language-javascript">          <span class="hljs-attr">type</span>: <span class="hljs-string">&#x27;GET&#x27;</span>,</span><br><span class="language-javascript">          <span class="hljs-attr">url</span>: <span class="hljs-string">&#x27;http://127.0.0.1/user&#x27;</span>,</span><br><span class="language-javascript">          <span class="hljs-attr">success</span>: <span class="hljs-keyword">function</span>(<span class="hljs-params">res</span>)&#123;</span><br><span class="language-javascript">            <span class="hljs-title function_">alert</span>(res.<span class="hljs-property">msg</span>)</span><br><span class="language-javascript">            <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(res)</span><br><span class="language-javascript">          &#125;,</span><br><span class="language-javascript">          <span class="hljs-attr">error</span>: <span class="hljs-keyword">function</span>(<span class="hljs-params">error</span>)&#123;</span><br><span class="language-javascript">            <span class="hljs-title function_">alert</span>(<span class="hljs-string">&#x27;出错了&#x27;</span>)</span><br><span class="language-javascript">            <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">error</span>(error)</span><br><span class="language-javascript">          &#125;</span><br><span class="language-javascript">        &#125;)</span><br><span class="language-javascript">      &#125;</span><br><span class="language-javascript">      <span class="hljs-keyword">function</span> <span class="hljs-title function_">login</span>(<span class="hljs-params"></span>)&#123;</span><br><span class="language-javascript">        <span class="hljs-keyword">const</span> reqData = &#123;</span><br><span class="language-javascript">          <span class="hljs-attr">name</span>: $(<span class="hljs-string">&quot;input[name=&#x27;name&#x27;]&quot;</span>).<span class="hljs-title function_">val</span>(),</span><br><span class="language-javascript">          <span class="hljs-attr">password</span>: $(<span class="hljs-string">&quot;input[name=&#x27;password&#x27;]&quot;</span>).<span class="hljs-title function_">val</span>()</span><br><span class="language-javascript">        &#125;</span><br><span class="language-javascript">        $.<span class="hljs-title function_">ajax</span>(&#123;</span><br><span class="language-javascript">          <span class="hljs-attr">url</span>: <span class="hljs-string">&#x27;http://127.0.0.1/login&#x27;</span>,</span><br><span class="language-javascript">          <span class="hljs-attr">type</span>: <span class="hljs-string">&#x27;POST&#x27;</span>,</span><br><span class="language-javascript">          <span class="hljs-attr">data</span>: reqData,</span><br><span class="language-javascript">          <span class="hljs-attr">dataType</span>: <span class="hljs-string">&#x27;json&#x27;</span>,</span><br><span class="language-javascript">          <span class="hljs-attr">success</span>: <span class="hljs-keyword">function</span>(<span class="hljs-params">res</span>)&#123;</span><br><span class="language-javascript">            <span class="hljs-title function_">alert</span>(res.<span class="hljs-property">msg</span>)</span><br><span class="language-javascript">            <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(res)</span><br><span class="language-javascript">          &#125;,</span><br><span class="language-javascript">          <span class="hljs-attr">error</span>: <span class="hljs-keyword">function</span>(<span class="hljs-params">error</span>)&#123;</span><br><span class="language-javascript">            <span class="hljs-title function_">alert</span>(<span class="hljs-string">&#x27;出错了&#x27;</span>)</span><br><span class="language-javascript">            <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">error</span>(error)</span><br><span class="language-javascript">          &#125;</span><br><span class="language-javascript">        &#125;) </span><br><span class="language-javascript">      &#125;</span><br><span class="language-javascript">    </span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span><br>  <span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span><br></code></pre></td></tr></table></figure>

<p>测试：</p>
<ul>
<li>后端使用 nodemon main.js 命令启动服务，URL为：<a target="_blank" rel="noopener" href="http://127.0.0.1/">http://127.0.0.1:80</a></li>
<li>前端使用 VSCode 的 Live Server 插件直接运行 index.html ，URL为：<a target="_blank" rel="noopener" href="http://127.0.0.1:5500/">http://127.0.0.1:5500</a></li>
</ul>
<h3 id="5-8-1-解决跨域问题"><a href="#5-8-1-解决跨域问题" class="headerlink" title="5.8.1 解决跨域问题"></a>5.8.1 解决跨域问题</h3><p>当点击查询用户后，出现了跨域警告，受同源策略的限制，当前 HTML 页面的 URL中的端口号 5500 和 Node.js 服务器的 80 不同，所以是不能直接访问的。</p>
<p><img src="https://img-blog.csdnimg.cn/10e8fef5e852444683b473097b8423aa.png" srcset="/img/loading.gif" lazyload alt="在这里插入图片描述"></p>
<p>报错信息：</p>
<blockquote>
<p>Access to XMLHttpRequest at ‘<a target="_blank" rel="noopener" href="http://127.0.0.1/user'">http://127.0.0.1/user'</a> from origin ‘<a href="http://127.0.0.1:5500&#39;">http://127.0.0.1:5500&#39;</a> has been blocked by CORS policy: No ‘Access-Control-Allow-Origin’ header is present on the requested resource.</p>
</blockquote>
<p>解决跨域方法主要有两种：CORS （常用）和 JSONP（只支持GET请求）</p>
<p>Node.js 中实现跨域很简单，直接安装 cors 中间件 然后 use 即可。实现步骤：</p>
<ol>
<li><p>安装 cors 包</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs shell">npm install cors<br></code></pre></td></tr></table></figure>
</li>
<li><p>导入cors</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs javascript"><span class="hljs-keyword">const</span> express = <span class="hljs-built_in">require</span>(<span class="hljs-string">&#x27;express&#x27;</span>)<br><span class="hljs-keyword">const</span> cors = <span class="hljs-built_in">require</span>(<span class="hljs-string">&#x27;cors&#x27;</span>)<br></code></pre></td></tr></table></figure>
</li>
<li><p>注册 cors</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs javascript">app = <span class="hljs-title function_">express</span>()<br>app.<span class="hljs-title function_">use</span>(<span class="hljs-title function_">cors</span>())		<span class="hljs-comment">// 注: 这一行要加载 app.use(router) 前面</span><br></code></pre></td></tr></table></figure></li>
</ol>
<h3 id="5-8-2-运行测试"><a href="#5-8-2-运行测试" class="headerlink" title="5.8.2 运行测试"></a>5.8.2 运行测试</h3><p>直接访问Node启动的服务器 ：<a target="_blank" rel="noopener" href="http://127.0.0.1/">http://127.0.0.1</a><br><img src="https://img-blog.csdnimg.cn/641c0a464e2048b5a93c9f252d442d51.png" srcset="/img/loading.gif" lazyload alt="在这里插入图片描述"></p>
<p>查看用户信息：<a target="_blank" rel="noopener" href="http://127.0.0.1/user">http://127.0.0.1/user</a></p>
<p>接着访问前端页面：<a href="http://127.0.0.1:5500，点击查询用户">http://127.0.0.1:5500，点击查询用户</a><br><img src="https://img-blog.csdnimg.cn/c3b4af7f93c743748a24ecd3e27fd005.png" srcset="/img/loading.gif" lazyload alt="在这里插入图片描述"></p>
<p>登录错误信息<br><img src="https://img-blog.csdnimg.cn/28902a9fcdbd44c0a7ee199c095de124.png" srcset="/img/loading.gif" lazyload alt="在这里插入图片描述"></p>
<p>登录正确信息<br><img src="https://img-blog.csdnimg.cn/ed848bd793204e9b9cc024f83ab41fde.png" srcset="/img/loading.gif" lazyload alt="在这里插入图片描述"></p>
<h2 id="5-9-案例——使用-JSONP-解决跨域"><a href="#5-9-案例——使用-JSONP-解决跨域" class="headerlink" title="5.9 案例——使用 JSONP 解决跨域"></a>5.9 案例——使用 JSONP 解决跨域</h2><p>JSONP：浏览器端通过 <script> 标签的 src 属性，请求服务器上的数据，同时服务器返回一个函数的调用。这种请求数据的方式叫做 JSONP</p>
<p>JSONP 的特点：</p>
<ol>
<li>JSONP 不属于 真正的 AJAX 请求，因为它没有使用 XMLHttpRequest 这个对象</li>
<li>JSONP 仅支持 GET 请求，不支持 POST、PUT、DELETE 等请求</li>
</ol>
<p>使用 JSONP 接口的注意事项：</p>
<ul>
<li>若项目中已经配置了 CORS 跨域资源共享，为防止冲突，必须在配置 CORS 中间件之间声明 JSONP 的接口，否则 JSONP 接口会被处理成开启了 CORS 的接口：</li>
</ul>
<p>实现 JSONP 接口的步骤：</p>
<ol>
<li>获取客户端发送过来的回调函数的名字</li>
<li>得到要通过 JSONP 形式发送给客户端的数据</li>
<li>根据前两步得到的数据，拼接出一个函数调用的字符串</li>
<li>把上一步拼接得到的字符串，响应给客户端的 <script> 标签进行解析执行</li>
</ol>
<p>项目结构：</p>
<figure class="highlight 1c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs 1c"><span class="hljs-string">|- index.html 	测试接口的 HTML 页面</span><br><br><span class="hljs-string">|- main.js			Node.js的Web服务器</span><br></code></pre></td></tr></table></figure>

<p><code>index.html</code></p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><code class="hljs html"><span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-keyword">html</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">&quot;en&quot;</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">&quot;UTF-8&quot;</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">&quot;viewport&quot;</span> <span class="hljs-attr">content</span>=<span class="hljs-string">&quot;width=device-width, initial-scale=1.0&quot;</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>Document<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">&quot;https://cdn.staticfile.org/jquery/3.6.0/jquery.min.js&quot;</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span><br><span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onclick</span>=<span class="hljs-string">&quot;queryUser()&quot;</span>&gt;</span>查询用户<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span><br>    <span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span><br>    <span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="language-javascript"></span><br><span class="language-javascript">        <span class="hljs-keyword">function</span> <span class="hljs-title function_">queryUser</span>(<span class="hljs-params"></span>)&#123;</span><br><span class="language-javascript">            $.<span class="hljs-title function_">ajax</span>(&#123;</span><br><span class="language-javascript">                <span class="hljs-attr">type</span>: <span class="hljs-string">&#x27;GET&#x27;</span>,</span><br><span class="language-javascript">                <span class="hljs-attr">url</span>: <span class="hljs-string">&#x27;http://127.0.0.1/jsonp&#x27;</span>,</span><br><span class="language-javascript">                <span class="hljs-attr">dataType</span>: <span class="hljs-string">&#x27;jsonp&#x27;</span>,</span><br><span class="language-javascript">                <span class="hljs-attr">success</span>: <span class="hljs-keyword">function</span>(<span class="hljs-params">res</span>)&#123;</span><br><span class="language-javascript">                    <span class="hljs-title function_">alert</span>(<span class="hljs-string">&#x27;请求成功&#x27;</span>)</span><br><span class="language-javascript">                    <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(res)</span><br><span class="language-javascript">                &#125;,</span><br><span class="language-javascript">                <span class="hljs-attr">error</span>: <span class="hljs-keyword">function</span>(<span class="hljs-params">error</span>)&#123;</span><br><span class="language-javascript">                    <span class="hljs-title function_">alert</span>(<span class="hljs-string">&#x27;出错了&#x27;</span>)</span><br><span class="language-javascript">                    <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">error</span>(error)</span><br><span class="language-javascript">                &#125;</span><br><span class="language-javascript">            &#125;)</span><br><span class="language-javascript">        &#125;</span><br><span class="language-javascript">        <span class="hljs-keyword">function</span> <span class="hljs-title function_">hello</span>(<span class="hljs-params"></span>)&#123;</span><br><span class="language-javascript">            <span class="hljs-title function_">alert</span>(<span class="hljs-string">&#x27;hello&#x27;</span>)</span><br><span class="language-javascript">        &#125;</span><br><span class="language-javascript">    </span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span><br><span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span><br></code></pre></td></tr></table></figure>

<p><code>main.js</code></p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><code class="hljs javascript"><span class="hljs-comment">//-------------------------------- 第三方包</span><br><span class="hljs-keyword">const</span> express = <span class="hljs-built_in">require</span>(<span class="hljs-string">&#x27;express&#x27;</span>)<br><br><span class="hljs-keyword">const</span> app = <span class="hljs-title function_">express</span>()<br><span class="hljs-comment">// JSONP 跨域</span><br>app.<span class="hljs-title function_">get</span>(<span class="hljs-string">&#x27;/jsonp&#x27;</span>, <span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> &#123;<br>    <span class="hljs-comment">// 得到函数的名称</span><br>    <span class="hljs-keyword">const</span> funcName = req.<span class="hljs-property">query</span>.<span class="hljs-property">callback</span><br>    <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(funcName)<br>    <span class="hljs-comment">// 定义要发送到客户端的数据对象</span><br>    <span class="hljs-keyword">const</span> data = &#123; <span class="hljs-attr">name</span>:<span class="hljs-string">&#x27;admin&#x27;</span>, <span class="hljs-attr">password</span>: <span class="hljs-string">&#x27;123456&#x27;</span>&#125;<br>    <span class="hljs-comment">// 拼接处函数的调用</span><br>    <span class="hljs-keyword">const</span> scriptStr = <span class="hljs-string">`<span class="hljs-subst">$&#123;funcName&#125;</span>(<span class="hljs-subst">$&#123;<span class="hljs-built_in">JSON</span>.stringify(data)&#125;</span>)`</span><br>    <span class="hljs-comment">// 把拼接的字符串，响应给客户端</span><br>    res.<span class="hljs-title function_">send</span>(scriptStr)<br>&#125;)<br>app.<span class="hljs-title function_">listen</span>(<span class="hljs-string">&#x27;80&#x27;</span>, <span class="hljs-function">() =&gt;</span>&#123;<br>    <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">&#x27;server is running at http://127.0.0.1:80&#x27;</span>)<br>&#125;)<br></code></pre></td></tr></table></figure>

<h2 id="5-10-案例——-Express-使用-Session"><a href="#5-10-案例——-Express-使用-Session" class="headerlink" title="5.10 案例—— Express 使用 Session"></a>5.10 案例—— Express 使用 Session</h2><ol>
<li><strong>安装 Session</strong><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs shell">npm install express-session<br></code></pre></td></tr></table></figure></li>
</ol>
<h2 id="5-11-案例-——-Express-使用-JWT"><a href="#5-11-案例-——-Express-使用-JWT" class="headerlink" title="5.11 案例 —— Express 使用 JWT"></a>5.11 案例 —— Express 使用 JWT</h2><ol>
<li><strong>安装 JWT 相关的包</strong></li>
</ol>
<ul>
<li>jsonwebtoken 用于生成 JWT 字符串</li>
<li>express-jwt 用于将 JWT 字符串解析还原成 JSON 对象<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs shell">npm install jsonwebtoken express-jwt<br></code></pre></td></tr></table></figure></li>
</ul>
<p>express-jwt  配置成功后，在有权限的接口里，使用 req.user 对象可以访问 从 JWT 字符串解析出来的用户信息</p>
<h1 id="6-跨域问题"><a href="#6-跨域问题" class="headerlink" title="6. 跨域问题"></a>6. 跨域问题</h1><hr>
<h2 id="6-1-CORS-跨域资源共享"><a href="#6-1-CORS-跨域资源共享" class="headerlink" title="6.1 CORS 跨域资源共享"></a>6.1 CORS 跨域资源共享</h2><p>CORS 即 Cross-Origin Resource Sharing，跨域资源共享）由一系列 HTTP 响应头组成，这些 HTTP 响应头决定浏览器是否阻止前端 JS 代码获取资源。</p>
<p>CORS 通常是在服务端配置的，客户端浏览器不用进行操作。</p>
<h2 id="6-2-CORS-响应头部"><a href="#6-2-CORS-响应头部" class="headerlink" title="6.2 CORS 响应头部"></a>6.2 CORS 响应头部</h2><h3 id="6-2-1-Access-Control-Allow-Origin"><a href="#6-2-1-Access-Control-Allow-Origin" class="headerlink" title="6.2.1 Access-Control-Allow-Origin"></a>6.2.1 Access-Control-Allow-Origin</h3><p>响应头部可携带一个 Access-Control-Allow-Origin 字段，其语法如下：</p>
<figure class="highlight gherkin"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs gherkin">Access-Control-Allow-Origin: <span class="hljs-variable">&lt;origin&gt;</span> |<span class="hljs-string"> *</span><br></code></pre></td></tr></table></figure>

<p>其中， origin 参数的值制定了允许访问该资源的外部域名 URL<br>【例】设置只允许来自 <a target="_blank" rel="noopener" href="http://uni.com/">http://uni.com</a> 的请求</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs javascript">res.<span class="hljs-title function_">setHeader</span>(<span class="hljs-string">&#x27;Access-Control-Allow-Origin&#x27;</span>, <span class="hljs-string">&#x27;http://uni.com&#x27;</span>)<br></code></pre></td></tr></table></figure>

<p>若指定 值为通配符 * ，那么则表示允许来自任何域的请求，例：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs javascript">res.<span class="hljs-title function_">setHeader</span>(<span class="hljs-string">&#x27;Access-Control-Allow-Origin&#x27;</span>, <span class="hljs-string">&#x27;*&#x27;</span>)<br></code></pre></td></tr></table></figure>
<h3 id="6-2-2-Access-Control-Allow-Headers"><a href="#6-2-2-Access-Control-Allow-Headers" class="headerlink" title="6.2.2 Access-Control-Allow-Headers"></a>6.2.2 Access-Control-Allow-Headers</h3><p>默认情况下，CORS 支持客户端向服务器发以下9种请求头：</p>
<ol>
<li>Accept</li>
<li>Accept-Language</li>
<li>Content-Language</li>
<li>DPR</li>
<li>Downlink</li>
<li>Save-Data</li>
<li>Viewport-Width</li>
<li>Width</li>
<li>Content-Type</li>
</ol>
<p>其中 Content-Type 的取值为以下三种之一：</p>
<ul>
<li>text/plain</li>
<li>multipart/form-data</li>
<li>application/x-www-form-urlencoded</li>
</ul>
<p>若客户端向服务器发送了除了上面九种以外其他的请求头信息，那么则需在服务端对 Access-Control-Allow-Header 额外的请求头进行声明，否则请求会失败。</p>
<h3 id="6-2-3-Access-Control-Allow-Methods"><a href="#6-2-3-Access-Control-Allow-Methods" class="headerlink" title="6.2.3 Access-Control-Allow-Methods"></a>6.2.3 Access-Control-Allow-Methods</h3><p>默认情况下，CORS 仅支持客户端发起 GET、POST、HEAD 请求，若客户端希望通过 PUT、DELETE 等方式请求服务器的资源，则需在服务器端通过 Access-Control-Allow-Methods 来指明实际请求所允许使用的 HTTP 方法。</p>
<h2 id="6-3-CORS-请求的分类"><a href="#6-3-CORS-请求的分类" class="headerlink" title="6.3 CORS 请求的分类"></a>6.3 CORS 请求的分类</h2><p>客户端在请求 CORS 接口时，根据请求方式和请求头的不同，可以将 CORS 的请求分为两大类，分别是：</p>
<ul>
<li>简单请求</li>
<li>预检请求</li>
</ul>
<h3 id="6-3-1-简单请求"><a href="#6-3-1-简单请求" class="headerlink" title="6.3.1 简单请求"></a>6.3.1 简单请求</h3><p>同时满足以下两个条件的请求：</p>
<ol>
<li>请求方式：GET、POST、HEAD 三者之一</li>
<li>HTTP 头部信息不超过以下几种字段：</li>
</ol>
<p>无定义的头部字段、Accept、Accept-Language、Content-Language、DPR、Downlink、Save-Data、Viewport-Width、Width、Content-Type</p>
<h3 id="6-3-2-预检请求"><a href="#6-3-2-预检请求" class="headerlink" title="6.3.2 预检请求"></a>6.3.2 预检请求</h3><p>只要符合以下任何一个条件的请求，都需要进行预检请求：</p>
<ol>
<li>请求方式为 GET、POST、HEAD 之外的请求 Method 类型</li>
<li>请求头中包含自定义的头部字段</li>
<li>向服务器发送了 application/json 的数据</li>
</ol>
<p>在浏览器与服务器正式通信之前，浏览器会先发送 OPTION 请求进行预检，以获知服务器是否允许该实际请求，所以这一次的 OPTION 请求称为"预检请求"。<br>服务器成功响应预检请求后，才会发送真正的请求，并且携带真实数据。</p>
<h3 id="6-3-3-简单请求与预见请求比较"><a href="#6-3-3-简单请求与预见请求比较" class="headerlink" title="6.3.3 简单请求与预见请求比较"></a>6.3.3 简单请求与预见请求比较</h3><p>简单请求：客户端与服务器之间只会发生一次请求<br>预检请求：客户端与服务器之间会发生两次请求，OPTION 预检请求成功后，才会发起真正的请求</p>
<h1 id="7-Node-操作-MySQL"><a href="#7-Node-操作-MySQL" class="headerlink" title="7. Node 操作 MySQL"></a>7. Node 操作 MySQL</h1><hr>
<ol>
<li><p><strong>安装 支持MySQL 的 Node拓展包</strong></p>
<figure class="highlight cmake"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs cmake">npm <span class="hljs-keyword">install</span> mysql<br></code></pre></td></tr></table></figure>
</li>
<li><p><strong>创建本地 SQL表</strong></p>
<figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br></pre></td><td class="code"><pre><code class="hljs sql"><span class="hljs-comment">/*</span><br><span class="hljs-comment"> Navicat Premium Data Transfer</span><br><span class="hljs-comment"></span><br><span class="hljs-comment"> Source Server         : 本机MYSQL</span><br><span class="hljs-comment"> Source Server Type    : MySQL</span><br><span class="hljs-comment"> Source Server Version : 50736</span><br><span class="hljs-comment"> Source Host           : localhost:3306</span><br><span class="hljs-comment"> Source Schema         : nodedemo</span><br><span class="hljs-comment"></span><br><span class="hljs-comment"> Target Server Type    : MySQL</span><br><span class="hljs-comment"> Target Server Version : 50736</span><br><span class="hljs-comment"> File Encoding         : 65001</span><br><span class="hljs-comment"></span><br><span class="hljs-comment"> Date: 19/08/2022 14:41:10</span><br><span class="hljs-comment">*/</span><br><br><span class="hljs-keyword">SET</span> NAMES utf8mb4;<br><span class="hljs-keyword">SET</span> FOREIGN_KEY_CHECKS <span class="hljs-operator">=</span> <span class="hljs-number">0</span>;<br><br><span class="hljs-comment">-- ----------------------------</span><br><span class="hljs-comment">-- Table structure for sys_user</span><br><span class="hljs-comment">-- ----------------------------</span><br><span class="hljs-keyword">DROP</span> <span class="hljs-keyword">TABLE</span> IF <span class="hljs-keyword">EXISTS</span> `sys_user`;<br><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> `sys_user`  (<br>  `id` <span class="hljs-type">bigint</span>(<span class="hljs-number">20</span>) <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> COMMENT <span class="hljs-string">&#x27;用户ID&#x27;</span>,<br>  `username` <span class="hljs-type">varchar</span>(<span class="hljs-number">255</span>) <span class="hljs-type">CHARACTER</span> <span class="hljs-keyword">SET</span> utf8mb4 <span class="hljs-keyword">COLLATE</span> utf8mb4_general_ci <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> COMMENT <span class="hljs-string">&#x27;用户名称&#x27;</span>,<br>  `password` <span class="hljs-type">varchar</span>(<span class="hljs-number">255</span>) <span class="hljs-type">CHARACTER</span> <span class="hljs-keyword">SET</span> utf8mb4 <span class="hljs-keyword">COLLATE</span> utf8mb4_general_ci <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> COMMENT <span class="hljs-string">&#x27;用户密码&#x27;</span>,<br>  `status` <span class="hljs-type">int</span>(<span class="hljs-number">11</span>) <span class="hljs-keyword">NULL</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-number">0</span> COMMENT <span class="hljs-string">&#x27;账号状态 0 正常 1 已删除&#x27;</span>,<br>  <span class="hljs-keyword">PRIMARY</span> KEY (`id`) <span class="hljs-keyword">USING</span> BTREE<br>) ENGINE <span class="hljs-operator">=</span> InnoDB <span class="hljs-type">CHARACTER</span> <span class="hljs-keyword">SET</span> <span class="hljs-operator">=</span> utf8mb4 <span class="hljs-keyword">COLLATE</span> <span class="hljs-operator">=</span> utf8mb4_general_ci ROW_FORMAT <span class="hljs-operator">=</span> <span class="hljs-keyword">Dynamic</span>;<br><br><span class="hljs-comment">-- ----------------------------</span><br><span class="hljs-comment">-- Records of sys_user</span><br><span class="hljs-comment">-- ----------------------------</span><br><span class="hljs-keyword">INSERT</span> <span class="hljs-keyword">INTO</span> `sys_user` <span class="hljs-keyword">VALUES</span> (<span class="hljs-number">1</span>, <span class="hljs-string">&#x27;a&#x27;</span>, <span class="hljs-string">&#x27;123456&#x27;</span>, <span class="hljs-number">0</span>);<br><span class="hljs-keyword">INSERT</span> <span class="hljs-keyword">INTO</span> `sys_user` <span class="hljs-keyword">VALUES</span> (<span class="hljs-number">2</span>, <span class="hljs-string">&#x27;admin&#x27;</span>, <span class="hljs-string">&#x27;123456&#x27;</span>, <span class="hljs-number">0</span>);<br><span class="hljs-keyword">INSERT</span> <span class="hljs-keyword">INTO</span> `sys_user` <span class="hljs-keyword">VALUES</span> (<span class="hljs-number">3</span>, <span class="hljs-string">&#x27;uni&#x27;</span>, <span class="hljs-string">&#x27;123456&#x27;</span>, <span class="hljs-number">0</span>);<br><br><span class="hljs-keyword">SET</span> FOREIGN_KEY_CHECKS <span class="hljs-operator">=</span> <span class="hljs-number">1</span>;<br></code></pre></td></tr></table></figure>
</li>
<li><p><strong>实现增删改查</strong></p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br></pre></td><td class="code"><pre><code class="hljs javascript"><span class="hljs-keyword">const</span> mysql = <span class="hljs-built_in">require</span>(<span class="hljs-string">&#x27;mysql&#x27;</span>)<br><br><span class="hljs-keyword">const</span> db = mysql.<span class="hljs-title function_">createPool</span>(&#123;<br>    <span class="hljs-attr">host</span>: <span class="hljs-string">&#x27;127.0.0.1&#x27;</span>,<br>    <span class="hljs-attr">user</span>: <span class="hljs-string">&#x27;root&#x27;</span>,<br>    <span class="hljs-attr">password</span>: <span class="hljs-string">&#x27;woaini&#x27;</span>,<br>    <span class="hljs-attr">database</span>: <span class="hljs-string">&#x27;nodedemo&#x27;</span><br>&#125;)<br><br><span class="hljs-comment">// 查询所有用户</span><br><span class="hljs-keyword">function</span> <span class="hljs-title function_">selectAllUser</span>(<span class="hljs-params"></span>)&#123;<br>    <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> &#123;<br>        db.<span class="hljs-title function_">query</span>(<span class="hljs-string">&#x27;SELECT * from sys_user WHERE status = 0&#x27;</span>, <span class="hljs-function">(<span class="hljs-params">err, results</span>) =&gt;</span> &#123;<br>            <span class="hljs-keyword">if</span>(err) <br>                <span class="hljs-keyword">return</span> <span class="hljs-title function_">reject</span>(err.<span class="hljs-property">message</span>)<br>            <span class="hljs-keyword">return</span> <span class="hljs-title function_">resolve</span>(results)<br>        &#125;)<br>    &#125;)<br> <br>&#125;<br><span class="hljs-comment">// 根据 ID 查询用户</span><br><span class="hljs-keyword">function</span> <span class="hljs-title function_">selectUserById</span>(<span class="hljs-params">id</span>)&#123;<br>    <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> &#123;<br>        db.<span class="hljs-title function_">query</span>(<span class="hljs-string">&#x27;SELECT * FROM sys_user WHERE id = ? AND status = 0&#x27;</span>, id, <span class="hljs-function">(<span class="hljs-params">err, results</span>) =&gt;</span>&#123;<br>            <span class="hljs-keyword">if</span>(err) <span class="hljs-keyword">return</span> <span class="hljs-title function_">reject</span>(err.<span class="hljs-property">message</span>)<br>            <span class="hljs-title function_">resolve</span>(results)<br>        &#125;)<br>    &#125;)<br>&#125;<br><span class="hljs-comment">// 根据 ID 修改用户信息</span><br><span class="hljs-keyword">function</span> <span class="hljs-title function_">updateUserById</span>(<span class="hljs-params">user</span>)&#123;<br>    <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> &#123;<br>        db.<span class="hljs-title function_">query</span>(<span class="hljs-string">&#x27;UPDATE sys_user SET ? WHERE id = ?&#x27;</span>, [user, user.<span class="hljs-property">id</span>], <span class="hljs-function">(<span class="hljs-params">err, results</span>) =&gt;</span>&#123;<br>            <span class="hljs-keyword">if</span>(err) <span class="hljs-keyword">return</span> <span class="hljs-title function_">reject</span>(err.<span class="hljs-property">message</span>)<br>            <span class="hljs-keyword">if</span>(results.<span class="hljs-property">affectedRows</span> === <span class="hljs-number">1</span>)&#123;<br>                <span class="hljs-title function_">resolve</span>(<span class="hljs-string">&#x27;Update the user[id=&#x27;</span> + user.<span class="hljs-property">id</span> + <span class="hljs-string">&#x27;] is successd!&#x27;</span>)<br>            &#125;<br>            <span class="hljs-title function_">reject</span>(results)<br>        &#125;)<br>    &#125;)<br>&#125;<br><br><span class="hljs-comment">// 根据 ID 删除用户</span><br><span class="hljs-keyword">function</span> <span class="hljs-title function_">deleteUserById</span>(<span class="hljs-params">id</span>)&#123;<br>    <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> &#123;<br>        db.<span class="hljs-title function_">query</span>(<span class="hljs-string">&#x27;UPDATE sys_user SET status = 1 WHERE id = ?&#x27;</span>, id, <span class="hljs-function">(<span class="hljs-params">err, results</span>) =&gt;</span> &#123;<br>            <span class="hljs-keyword">if</span>(err) <span class="hljs-keyword">return</span> <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(err.<span class="hljs-property">message</span>)<br>            <span class="hljs-keyword">if</span>(results.<span class="hljs-property">affectedRows</span> === <span class="hljs-number">1</span>)&#123;<br>                <span class="hljs-title function_">resolve</span>(<span class="hljs-string">&#x27;Delete the user[id=&#x27;</span> + id + <span class="hljs-string">&#x27;] is successd!&#x27;</span>) <br>            &#125; <span class="hljs-keyword">else</span><br>                <span class="hljs-title function_">reject</span>(<span class="hljs-string">&#x27;Delete denied.&#x27;</span>)<br>        &#125;)<br>    &#125;)<br>&#125;<br></code></pre></td></tr></table></figure>
</li>
<li><p><strong>测试效果</strong></p>
</li>
</ol>
<p>查询所有用户</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs javascript"><span class="hljs-title function_">selectAllUser</span>().<span class="hljs-title function_">then</span>(<br>    <span class="hljs-function">(<span class="hljs-params">results</span>) =&gt;</span> &#123;<br>        <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">&#x27;查询结果: &#x27;</span>, results)<br>    &#125;,<br>    <span class="hljs-function">() =&gt;</span> <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">&#x27;查询失败&#x27;</span>)<br>).<span class="hljs-title function_">catch</span>(<span class="hljs-function">(<span class="hljs-params">err</span>) =&gt;</span> &#123;<span class="hljs-variable language_">console</span>.<span class="hljs-title function_">error</span>(<span class="hljs-string">&#x27;出错了&#x27;</span>, err)&#125;)<br></code></pre></td></tr></table></figure>
<blockquote>
<p>运行结果<br>查询结果:  [<br>  RowDataPacket { id: 1, username: 'a', password: '123456', status: 0 },<br>  RowDataPacket {<br>    id: 2,<br>    username: 'admin',<br>    password: '123456',<br>    status: 0<br>  },<br>  RowDataPacket {<br>    id: 3,<br>    username: 'uni',<br>    password: '123456',<br>    status: 0<br>  }<br>]</p>
</blockquote>
<p>根据 ID 查询用户</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs javascript"><span class="hljs-title function_">selectUserById</span>(<span class="hljs-number">1</span>).<span class="hljs-title function_">then</span>(<br>    <span class="hljs-function">(<span class="hljs-params">results</span>) =&gt;</span> &#123;<br>        <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">&#x27;查询结果: &#x27;</span>, results)<br>    &#125;,<br>    <span class="hljs-function">() =&gt;</span> <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">&#x27;查询失败&#x27;</span>)<br>).<span class="hljs-title function_">catch</span>(<span class="hljs-function">(<span class="hljs-params">err</span>) =&gt;</span> &#123;<span class="hljs-variable language_">console</span>.<span class="hljs-title function_">error</span>(<span class="hljs-string">&#x27;出错了&#x27;</span>, err)&#125;)<br></code></pre></td></tr></table></figure>
<blockquote>
<p>运行结果<br>查询结果:  [<br>  RowDataPacket { id: 1, username: 'a', password: '123456', status: 0 }<br>]</p>
</blockquote>
<p>修改用户信息</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs javascript"><span class="hljs-title function_">updateUserById</span>(&#123;<span class="hljs-attr">id</span>: <span class="hljs-number">1</span>, <span class="hljs-attr">username</span>: <span class="hljs-string">&#x27;hi&#x27;</span>&#125;).<span class="hljs-title function_">then</span>(<br>    <span class="hljs-function">(<span class="hljs-params">results</span>) =&gt;</span> &#123;<br>        <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">&#x27;修改结果: &#x27;</span>, results)<br>    &#125;,<br>    <span class="hljs-function">() =&gt;</span> <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">&#x27;查询失败&#x27;</span>)<br>).<span class="hljs-title function_">catch</span>(<span class="hljs-function">(<span class="hljs-params">err</span>) =&gt;</span> &#123;<span class="hljs-variable language_">console</span>.<span class="hljs-title function_">error</span>(<span class="hljs-string">&#x27;出错了&#x27;</span>, err)&#125;)<br></code></pre></td></tr></table></figure>
<blockquote>
<p>运行结果<br>修改结果:  Update the user[id=1] is successd!</p>
</blockquote>
<p>删除用户（本质上只设置 status 字段值为1 ）</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs javascript"><span class="hljs-title function_">deleteUserById</span>(<span class="hljs-number">1</span>).<span class="hljs-title function_">then</span>(<br>    <span class="hljs-function">(<span class="hljs-params">results</span>) =&gt;</span> &#123;<br>        <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">&#x27;删除结果: &#x27;</span>, results)<br>    &#125;,<br>    <span class="hljs-function">() =&gt;</span> <span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(<span class="hljs-string">&#x27;查询失败&#x27;</span>)<br>).<span class="hljs-title function_">catch</span>(<span class="hljs-function">(<span class="hljs-params">err</span>) =&gt;</span> &#123;<span class="hljs-variable language_">console</span>.<span class="hljs-title function_">error</span>(<span class="hljs-string">&#x27;出错了&#x27;</span>, err)&#125;)<br></code></pre></td></tr></table></figure>
<blockquote>
<p>运行结果<br>删除结果:  Delete the user[id=1] is successd!</p>
</blockquote>
<p>至此，案例测试完毕</p>

                
              </div>
            
            <hr/>
            <div>
              <div class="post-metas my-3">
  
    <div class="post-meta mr-3 d-flex align-items-center">
      <i class="iconfont icon-category"></i>
      

<span class="category-chains">
  
  
    
      <span class="category-chain">
        
  <a href="/categories/%E5%89%8D%E7%AB%AF/" class="category-chain-item">前端</a>
  
  

      </span>
    
  
</span>

    </div>
  
  
    <div class="post-meta">
      <i class="iconfont icon-tags"></i>
      
        <a href="/tags/Node/">#Node</a>
      
    </div>
  
</div>


              
  

  <div class="license-box my-3">
    <div class="license-title">
      <div>Node 笔记1 _ 常用内置 API _ 模块化编程 _ 自定义 npm包并发布到官方 _ Express 模块的使用 _ Node 解决跨域问题 _ Node 操作 MySQL</div>
      <div>http://example.com/2022/08/22/Node 笔记1 _ 常用内置 API _ 模块化编程 _ 自定义 npm包并发布到官方 _ Express 模块的使用 _ Node 解决跨域问题 _ Node 操作 MySQL/</div>
    </div>
    <div class="license-meta">
      
        <div class="license-meta-item">
          <div>作者</div>
          <div>John Doe</div>
        </div>
      
      
        <div class="license-meta-item license-meta-date">
          <div>发布于</div>
          <div>2022年8月22日</div>
        </div>
      
      
      <div class="license-meta-item">
        <div>许可协议</div>
        <div>
          
            
            
              <a target="_blank" href="https://creativecommons.org/licenses/by/4.0/">
              <span class="hint--top hint--rounded" aria-label="BY - 署名">
                <i class="iconfont icon-by"></i>
              </span>
              </a>
            
          
        </div>
      </div>
    </div>
    <div class="license-icon iconfont"></div>
  </div>



              
                <div class="post-prevnext my-3">
                  <article class="post-prev col-6">
                    
                    
                      <a href="/2022/08/22/%E4%B8%80%E9%94%AE%E4%B8%8B%E8%BD%BDCSDN%E5%8D%9A%E5%AE%A2%E6%89%80%E6%9C%89%E7%9A%84%E6%96%87%E7%AB%A0/" title="一键下载CSDN博客所有的文章">
                        <i class="iconfont icon-arrowleft"></i>
                        <span class="hidden-mobile">一键下载CSDN博客所有的文章</span>
                        <span class="visible-mobile">上一篇</span>
                      </a>
                    
                  </article>
                  <article class="post-next col-6">
                    
                    
                      <a href="/2022/08/21/C%E8%AF%AD%E8%A8%80%20%E5%AE%9E%E7%8E%B0%E8%B4%AA%E5%90%83%E8%9B%87%20_%20%E5%8D%81%E5%88%86%E9%92%9F%E5%85%A5%E9%97%A8%E6%A1%88%E4%BE%8B%20_%20%E5%88%9D%E5%AD%A6%E8%80%85%E6%A1%88%E4%BE%8B%20_%20%E9%99%84%E5%B8%A6%E8%AE%BE%E8%AE%A1%E6%80%9D%E8%B7%AF%20+%20%E4%BB%A3%E7%A0%81%20+%20%E5%9B%BE%E6%96%87%E5%88%86%E6%9E%90/" title="C语言 实现贪吃蛇 _ 十分钟入门案例 _ 初学者案例 _ 附带设计思路 + 代码 + 图文分析">
                        <span class="hidden-mobile">C语言 实现贪吃蛇 _ 十分钟入门案例 _ 初学者案例 _ 附带设计思路 + 代码 + 图文分析</span>
                        <span class="visible-mobile">下一篇</span>
                        <i class="iconfont icon-arrowright"></i>
                      </a>
                    
                  </article>
                </div>
              
            </div>

            
          </article>
        </div>
      </div>
    </div>

    <div class="side-col d-none d-lg-block col-lg-2">
      
  <aside class="sidebar" style="margin-left: -1rem">
    <div id="toc">
  <p class="toc-header"><i class="iconfont icon-list"></i>&nbsp;目录</p>
  <div class="toc-body" id="toc-body"></div>
</div>



  </aside>


    </div>
  </div>
</div>





  



  



  



  



  







    

    
      <a id="scroll-top-button" aria-label="TOP" href="#" role="button">
        <i class="iconfont icon-arrowup" aria-hidden="true"></i>
      </a>
    

    
      <div class="modal fade" id="modalSearch" tabindex="-1" role="dialog" aria-labelledby="ModalLabel"
     aria-hidden="true">
  <div class="modal-dialog modal-dialog-scrollable modal-lg" role="document">
    <div class="modal-content">
      <div class="modal-header text-center">
        <h4 class="modal-title w-100 font-weight-bold">搜索</h4>
        <button type="button" id="local-search-close" class="close" data-dismiss="modal" aria-label="Close">
          <span aria-hidden="true">&times;</span>
        </button>
      </div>
      <div class="modal-body mx-3">
        <div class="md-form mb-5">
          <input type="text" id="local-search-input" class="form-control validate">
          <label data-error="x" data-success="v" for="local-search-input">关键词</label>
        </div>
        <div class="list-group" id="local-search-result"></div>
      </div>
    </div>
  </div>
</div>

    

    
  </main>

  <footer>
    <div class="footer-inner">
  
    <div class="footer-content">
       <a href="https://hexo.io" target="_blank" rel="nofollow noopener"><span>Hexo</span></a> <i class="iconfont icon-love"></i> <a href="https://github.com/fluid-dev/hexo-theme-fluid" target="_blank" rel="nofollow noopener"><span>Fluid</span></a> 
    </div>
  
  
  
  
</div>

  </footer>

  <!-- Scripts -->
  
  <script  src="https://lib.baomitu.com/nprogress/0.2.0/nprogress.min.js" ></script>
  <link  rel="stylesheet" href="https://lib.baomitu.com/nprogress/0.2.0/nprogress.min.css" />

  <script>
    NProgress.configure({"showSpinner":false,"trickleSpeed":100})
    NProgress.start()
    window.addEventListener('load', function() {
      NProgress.done();
    })
  </script>


<script  src="https://lib.baomitu.com/jquery/3.6.0/jquery.min.js" ></script>
<script  src="https://lib.baomitu.com/twitter-bootstrap/4.6.1/js/bootstrap.min.js" ></script>
<script  src="/js/events.js" ></script>
<script  src="/js/plugins.js" ></script>


  <script  src="https://lib.baomitu.com/typed.js/2.0.12/typed.min.js" ></script>
  <script>
    (function (window, document) {
      var typing = Fluid.plugins.typing;
      var subtitle = document.getElementById('subtitle');
      if (!subtitle || !typing) {
        return;
      }
      var text = subtitle.getAttribute('data-typed-text');
      
        typing(text);
      
    })(window, document);
  </script>




  
    <script  src="/js/img-lazyload.js" ></script>
  




  
<script>
  Fluid.utils.createScript('https://lib.baomitu.com/tocbot/4.18.2/tocbot.min.js', function() {
    var toc = jQuery('#toc');
    if (toc.length === 0 || !window.tocbot) { return; }
    var boardCtn = jQuery('#board-ctn');
    var boardTop = boardCtn.offset().top;

    window.tocbot.init({
      tocSelector     : '#toc-body',
      contentSelector : '.markdown-body',
      headingSelector : CONFIG.toc.headingSelector || 'h1,h2,h3,h4,h5,h6',
      linkClass       : 'tocbot-link',
      activeLinkClass : 'tocbot-active-link',
      listClass       : 'tocbot-list',
      isCollapsedClass: 'tocbot-is-collapsed',
      collapsibleClass: 'tocbot-is-collapsible',
      collapseDepth   : CONFIG.toc.collapseDepth || 0,
      scrollSmooth    : true,
      headingsOffset  : -boardTop
    });
    if (toc.find('.toc-list-item').length > 0) {
      toc.css('visibility', 'visible');
    }
  });
</script>


  <script src=https://lib.baomitu.com/clipboard.js/2.0.10/clipboard.min.js></script>

  <script>Fluid.plugins.codeWidget();</script>


  
<script>
  Fluid.utils.createScript('https://lib.baomitu.com/anchor-js/4.3.1/anchor.min.js', function() {
    window.anchors.options = {
      placement: CONFIG.anchorjs.placement,
      visible  : CONFIG.anchorjs.visible
    };
    if (CONFIG.anchorjs.icon) {
      window.anchors.options.icon = CONFIG.anchorjs.icon;
    }
    var el = (CONFIG.anchorjs.element || 'h1,h2,h3,h4,h5,h6').split(',');
    var res = [];
    for (var item of el) {
      res.push('.markdown-body > ' + item.trim());
    }
    if (CONFIG.anchorjs.placement === 'left') {
      window.anchors.options.class = 'anchorjs-link-left';
    }
    window.anchors.add(res.join(', '));
  });
</script>


  
<script>
  Fluid.utils.createScript('https://lib.baomitu.com/fancybox/3.5.7/jquery.fancybox.min.js', function() {
    Fluid.plugins.fancyBox();
  });
</script>


  <script>Fluid.plugins.imageCaption();</script>

  <script  src="/js/local-search.js" ></script>





<!-- 主题的启动项，将它保持在最底部 -->
<!-- the boot of the theme, keep it at the bottom -->
<script  src="/js/boot.js" ></script>


  

  <noscript>
    <div class="noscript-warning">博客在允许 JavaScript 运行的环境下浏览效果更佳</div>
  </noscript>
</body>
</html>
